Home > Software engineering >  JS Algorthim - CodeCamp
JS Algorthim - CodeCamp

Time:07-23

wonder if you could help me understand this a little further; tried to use the debugger and various console logs to see where it's failing but still not entirely sure.


Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching name and value pairs (second argument). Each name and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.

For example, if the first argument is [{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], and the second argument is { last: "Capulet" }, then you must return the third object from the array (the first argument), because it contains the name and its value, that was passed on as the second argument.


Below is the code not working on the given function below; it should return the following:

[{ "apple": 1, "bat": 2, "cookie": 2 }]

However, all three objects are returned instead of just the one.

p.s. excuse the variable naming convention

function whatIsInAName(collection, source) {
  const arr = [];

  collection.filter(function (obj) {
    const objKeysInSrc = Object.keys(source);

    objKeysInSrc.every(function (keyVal) {
      console.log(keyVal);
      console.log(obj[keyVal]);
      console.log(source[keyVal]);

      console.log(obj.hasOwnProperty(keyVal));

      if (obj.hasOwnProperty(keyVal) && obj[keyVal] === source[keyVal]) {
        console.log("match");
        arr.push(obj);
      }
    });
  });
  console.log(arr);
  return arr;
}

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

Now this code below works perfectly fine

function whatIsInAName(collection, source) { 
  const filtArr = collection
    .filter(prop => Object.keys(source)
    .every(value => prop
    .hasOwnProperty(value) && prop[value] === source[value]));
 
  return filtArr;
}

I'm curious to know what could be wrong here as the given test cases work but others fail.

This given function call works:

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

CodePudding user response:

You are not correctly using array methods:

  • The callback to filter should return whether the current item should be included or not, and filter will return a new array that has the included items. So you need:

    • To return something in the callback
    • Capture the array that is returned by .filter.
  • The callback to every should return whether the current item is OK or not, and every will return a boolean whether all items are OK or not. So you need:

    • To return something in the callback
    • Capture the boolean that is returned by .every
  • The callback to every currently pushes an item to arr when just one key matches, but:

    • You should only retain an object when every key of the source object is present, not just one
    • Using arr.push inside a every (or filter) callback is an anti-pattern. The idea is that you use whatever these methods return.

The correct solution that you posted, does all these things right.

CodePudding user response:

Thanks for this, was helpful. Managed to get it working

function whatIsInAName(collection, source) {
 
  const newCollection = collection
    .filter(function(obj) { 
      return Object.keys(source)
      .every(function(keyVal) { 
      if (obj.hasOwnProperty(keyVal) && obj[keyVal] === source[keyVal]) {
          return obj;
      }
    })
  })
  return newCollection;
}
  • Related