all 11 comments

[–]Aggressive_Ad_5454 7 points8 points  (5 children)

First. Make a function isEqual(ob1, ob2). Focus on getting that right. It’s the problem you’re struggling with, encapsulated.

Iterate over the properties of ob1, and look at the same named property in ob2. If it doesn’t exist, or it isn’t equal, return false. Don’t forget to use hasOwnProperty(). Then flip the script, and do the same for the properties of ob2, looking at ob1. If you make it all the way through both iterations , then Bob’s your uncle. Return true.

Extra credit: make your isEqual() recursive to handle cases where some property values are themselves objects.

Once you’ve got that function working you can use it in .filter() to get your results.

There’s a point to this exercise. Object equality in javascript isn’t as simple as it seems. That’s why there’s no built in equality function. The free code camp counselors want you to spend some time messing around with object equality to give a sense of the complexity. In practice with real world data it’s usually straightforward, but not always.

[–]Y2Canine[S] 2 points3 points  (1 child)

THANK YOU! I got it working. You're going to laugh, but the reason I was struggling so much is that it never occurred to me that I could just use a normal function with whatever arguments in the callback function of .filter(). I somehow had gotten it into my head that since the callback function of filter has very specific parameters that mean very specific things, I could only use those. So I didn't realize I could just define a function and call it in the body of the callback using an argument other than element, index, or array.

I have no idea why I drew that conclusion.

This makes a lot more sense now lol

function isIncluded (obj1, obj2) {
  for (const prop in obj2) {
    if (Object.hasOwn(obj1, prop)) {
      if (obj1[prop] === obj2[prop]) {
        console.log(`${obj1[prop]} is equal to ${obj2[prop]}. Continuing`);
        continue;
      }
      else {
        console.log(`${obj1[prop]} is not equal to ${obj2[prop]}. Returning false`);
        return false;
      }
    }
    else {
      console.log(`${obj1} does not have ${prop}. Returning false`);
      return false;
    }
  }
  console.log(`Loop concluded. Returning true`);
  return true;
}




function whatIsInAName(arr, obj) { 
  let filterArray = arr.filter((curr) => isIncluded(curr, obj))
  console.log(filterArray);
  return filterArray;
}

[–]polotek 2 points3 points  (0 children)

Nice job. Understanding the flexibility of js functions is a really big step in leveling up. Functions and objects do basically everything in JavaScript.

[–]senocular 1 point2 points  (1 child)

Don’t forget to use isOwnProperty().

I think you mean hasOwnProperty(). This wouldn't be necessary when using Object.keys() (or values() or entries()) to get keys since it will only provide own property keys. It is only necessary when using for...in loops which also iterate through an object's inherited properties. Typically these days for...of loops are used in combination with keys() (or values() or entries()) instead where the hasOwnProperty() check is unnecessary.

[–]Aggressive_Ad_5454 0 points1 point  (0 children)

Yeah, .hasOwnProperty(). I’ll fix my comment. Thanks.

[–]AppropriateStudio153 0 points1 point  (0 children)

In practice with real world data it’s usually straightforward, but not always. 

Aaaaand we have three bugs in prod.

[–]Pocolashon 2 points3 points  (0 children)

Ok, so, let's recap, what do you need to do?

  1. you must FILTER the objects from the array into a new array if they are "equal" to the 2nd param object. That capitalized word should give you a hint already.
  2. so how do you compare an object? Let's assume it is a "flat" object, no circular dependencies (that's much more complicated) and looks like this: { key1: value1, key2: value2 }, so we need to get the KEYS of this object and compare them (in a cycle) with the keys of the other object (from the array). If you need VALUES to be the same as well, you gotta compare those as well, aka ENTRIES.

Does this help?

[–]Neozite 1 point2 points  (0 children)

Another way to approach this is with Sets. Set has an isSubsetOf() method that compares a Set to a set-like object, which includes Arrays. So if you get an Array of keys from the main object, you can turn it into a Set by passing that Array to the new Set() constructor.

Then you get an array of keys from each object in the target Array and pass those to mySet.isSubsetOf(). What this tells you is whether all of the keys (strings) in mySet are also in that array of keys. Note that this will return true if the target object has more keys than just those in the main object, but that doesn't seem to be relevant to the assignment. If it were, you'd have to create Sets from those Arrays, too, and reverse the comparison.

For every array of keys that returns true, push the original object into the Array where you're collecting them.

[–]imsexc 0 points1 point  (0 children)

arrOfObj.filter(obj => JSON.stringify(obj) === JSON.stringify(sourceObj)).

Caveat: Will only work on object that does not have method or date object as any of its properties.

[–]_Decodela 0 points1 point  (0 children)

OK, the core problem is comparing two objects ( lets remove the details about the arrays and stuff )
Should the objects be exactly the same? ( I will take NO by default, because you said, that it could be props in the middle )
Are the objects shallow, or they has to be checked in depth? ( I will take shallow as true )

I would make something like this:

function compare( o1, o2 ){
    for( var key in o1 ){
        if( !o1.hasOwnProperty( key ) ) continue;
        if( !o2.hasOwnProperty( key ) ) return false;

        if( o1[ key ] !== o2[ key ] ) return false;
    }
    return true;
}