Wherefore art thou - JavaScript Solution and Walkthrough

(04/21) Learn how to solve coding challenges using FreeCodeCamp's curriculum.

Wherefore art thou - JavaScript Solution and Walkthrough

04/21 Wherefore art thou

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.

function whatIsInAName(collection, source) {
  let arr = [];
  // Only change code below this line

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

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

Credit: FreeCodeCamp.org

Understanding the Challenge

In this challenge, the function will be passed two arguments. The first arguments collection will be an array of objects. And the second argument source will be an object.

Our task is to complete the function such that it will return all the object in the collection that contains all the key value pairs of the source object. The final array to be returned must have all the elements of the argument present in it.

In the example above, the first argument is given as [{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }] and the second argument is given as { last: "Capulet" }

In this case, it is expected that the whatIsInAName function will return [{ first: "Tybalt", last: "Capulet" }]. This is because of all the three objects in the collection, it is the only that contains the key value pair found in the source object.

Pseudocode

Given collection(an array of object) and source(an object)
  Extract all keys found in the source object
  Loop through the collection array
    For each iteration, check if the current fulfills two conditions
    First, object contains all keys present in source
    Second, the corresponding values of the keys are same as those in source
Return an array of all objects in collection that fulfills these conditions

Solving the Challenge

First, we need to get all the keys in the source objects. We can do so by using Object.keys. Let's save the keys in a variable called sourceKeys.

let sourceKeys = Object.keys(source);

console.log(sourceKeys) // [ 'last' ]

To get which of the objects in the collection array fulfills the two conditions we mentioned in our pseudocode, we will use both the .filter() and .every() methods.

You may be asking why need both methods.

We will apply the filter methods on the collection array. This way will get the objects one by one.

And then we'll apply the .every() on the source object. This will return either true or false. For each object, it will return true if our two conditions are met. Otherwise, it will return false.

arr = collection.filter((obj) => {
  return sourceKeys.every((key) => {
    return obj.hasOwnProperty(key) && obj[key] === source[key]
  })
})

Pay attention to how we are checking whether the current object fulfills the two conditions. First we use .hasOwnProperty(). This method helps us to check whether the key is present in the current object.

And then we obj[key] === source[key] to compare the value of the key in obj and source. This is important because we can have a situation where a key may be present in both obj and source but the values may not be equal. In that case we want .every() to return false.

We can now return arr and our function is complete.

Final Solution

function whatIsInAName(collection, source) {
  let arr = [];
  let sourceKeys = Object.keys(source);

  arr = collection.filter((obj) => {
     return sourceKeys.every((key) => {
       return obj.hasOwnProperty(key) && obj[key] === source[key];
     });
  });

  return arr;
}

Congratulations! You just cracked the "Seek and Destroy" algorithm challenge. Cheers and happy coding!

Let's connect on Twitter