Wherefore art thou - intermediate algorithm [please help]

Tell us what’s happening:

My code is passing all but the last test. I’ve looked through it and can’t see why it doesn’t pass the last test, which is whatIsInAName([{"a": 1, "b": 2, "c": 3}], {"a": 1, "b": 9999, "c": 3})

I’m probably missing something fairly obvious. Can someone please help guide me to it?

Your code so far


function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  const sourceKeys = Object.keys(source)

  for (let i = 0; i < collection.length; i++) {
    let collectionIKeys = Object.keys(collection[i])
    for (let key of sourceKeys) {

      if (sourceKeys.every(elem => collectionIKeys.includes(elem)) && collection[i][key] === source[key]) {

        arr.push(collection[i])
        break;
      }
    }
  }

  // Only change code above this line
  return arr;
}

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36.

Link to the challenge:

Try With this

function whatIsInAName(collection, source) {
  // "What's in a name? 
  var srcKeys = Object.keys(source);

  // filter the collection
  return collection.filter(function (obj) {
    return srcKeys
      .map(function(key) {
        return obj.hasOwnProperty(key) && obj[key] === source[key];
      })
      .reduce(function(a, b) {
        return a && b;
      });
  });
}

// test here
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });

Thanks Gunjan. I tried typing your code in but it says cannot convert undefined or null to object

It is rather different to my initial solution though. Do you have any ideas how I can get mine to pass?

The line that is causing your code to fail the last test is:

if (sourceKeys.every(elem => collectionIKeys.includes(elem)) && collection[i][key] === source[key]) {

Looking at just the first loop through the for (let key of sourceKeys) { ... }

In your if statement sourceKeys.every(elem => collectionIKeys.includes(elem)) gets evaluated first and returns TRUE because all of the keys in the object you are comparing to the source exist in both. Your if statement then is seen by JS as:

if (TRUE && collection[i][key] === source[key]) {

So now JS tests to see if collection[i][key] === source[key]. This only tests to see if the current key (which on the first loop is a) is on the source object. Since collection[0]['a'] === source['a'] is TRUE, your if code block is executed and the item is pushed into your array.

To fix the issue. Move the && operator and all the comparison code to its’ right into your arrow function. Doing this alone won’t fix it quite yet because you are still referencing key. Reference elem instead and your code will check to see if the current comparison object has all the keys the source has AND if their values are the same. If you want a spoiler. I can post the fixed line :slight_smile:.

Thank you so much @imi-tating!

I changed my if statement to if (sourceKeys.every(elem => collectionIKeys.includes(elem) && collection[i][elem]=== source[elem])) and it passed.

I can’t believe half of my problem was having a parenthesis in the wrong place! The joys of writing code :grinning:

1 Like