Trouble with Wherefore Art Thou JS Challenge

Hi Everyone,

I’ve been having a lot of trouble with the “Wherefore Art Though” Intermediate Algorithm Scripting Challenge. I’ve been trying to figure it out for a day and a half now and so far my code has only been able to pass 4 of the 6 tests. I didn’t have too much trouble on the Basic Algorithm Scripting challenges, and was able to complete the first 3 intermediate ones without hints, but this one has thrown me for a loop!

My main struggle now is that I don’t know how to check the value of a given key in a given object in the Collection array matches the given value of a given key in the Source object.

What’s the best way to go about this? Am I on the right track with my current code? Any help would be greatly appreciated.

  const arr = [];
  // Only change code below this line
let sourceKeys = Object.keys(source);
let sourceValues = Object.values(source);

collection.forEach((obj) => {
  let checkAllKeys = sourceKeys.every((i) => obj.hasOwnProperty(i));
  if (checkAllKeys === true) {
    arr.push(obj)
  }
})
  // Only change code above this line
  return arr;
}

whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "cookie": 2 }); ```

You are very close to solving the challenge.

For each object in collection, you are currently checking if every property of the source object exists in the object.

Let’s step back a moment and look at an example of how you would approach the part you are stuck on.

const obj1 = {
  a: 1
  b: 2
  c: 3
};

const obj2 = {
  a: 1
  b: 2
  c: 3
};

Answer this question: How would you check if obj1’s a property value matches obj2’s a property value?

obj1.a === obj2.a would return a true or false value, but I’m not sure how to include that test in a loop to check each value.

OK, you are 99% there:

const obj1 = {
  a: 1
  b: 2
  c: 3
};

const obj2 = {
  a: 1
  b: 2
  c: 3
};

const i = 'b';

One more question: How would you check if obj1’s property (named with the same value of i) value matches obj2’s property (named with the same value of i) value? In the example above, how would you check that both objects have the same value for property b using the i variable?

HINT: Review this challenge or additional help.

Thank you @RandellDawson !!! That helped make things click for me a little bit and I was able to figure it out and come up with a working solution now. It may not be pretty or elegant, but it works. See below.

  const arr = [];
  // Only change code below this line
let sourceKeys = Object.keys(source);
let sourceValues = Object.values(source);

collection.forEach((obj) => {
  let checkAllKeys = sourceKeys.every((i) => obj.hasOwnProperty(i));
  let checkAllValues = sourceValues.every((j) => Object.values(obj).includes(j))
  if (checkAllKeys === true && checkAllValues === true) {
    arr.push(obj)
  }
})
  // Only change code above this line
  return arr;
}
whatIsInAName([{"a": 1, "b": 2, "c": 3}], {"a": 1, "b": 9999, "c": 3});```

You do not need two every methods. You just need to add the other condition in the return statement of the first every method.

Also, in case you forgot or did not know:

if (checkAllKeys === true) {

is the same as writing:

if (checkAllKeys) {

Also, the following is risky:

Object.values(obj).includes(j)

What if two properties had the same value? There is not a test case for this, but if there was, your function could return the wrong value.

Another case would be if the following call was made:

whatIsInAName([{"a": 1, "b": 2, "c": 3, "d": 9999}], {"a": 1, "b": 9999, "c": 3})

Your function would incorrectly return [ { a: 1, b: 2, c: 3, d: 9999 } ] instead of the correct return of [].

There is a much simpler solution if you just use the hints I already gave you. There was nothing in the challenge I linked about using the includes method.

@RandellDawson Great points, even though it passed there were definitely some issues with my code. I’ve thought about what you said, and after looking at the code for awhile, doing some console.logging and banging my head against the wall for a bit, I think I have a better solution.

Is something like this what you had in mind?

I added a second condition to the checkAllKeys variable so it checks if obj[i] === source[i]. What you said about using variables to access object properties was a major piece of the puzzle that I was missing and helped me figure this out. Thank you!

  const arr = [];
  // Only change code below this line
let sourceKeys = Object.keys(source);
let sourceValues = Object.values(source);

collection.forEach((obj) => {
let checkAllKeys = sourceKeys.every((i) => obj.hasOwnProperty(i) && obj[i] === source[i]);
 if (checkAllKeys) {
    arr.push(obj)
  }
})
  // Only change code above this line
  return arr;
}

whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "cookie": 2 });```
1 Like

You don’t need this line anymore.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.