Implement a Matching Object Filter - Implement a Matching Object Filter

Tell us what’s happening:

I’ve been stuck on this Lab for the past few hours and have tried to accomplish it with multiple different paths (as you can see from all the commented out lines of code).

Ultimately I am unsure how I can properly validate if each object within the array contains all the respective properties & values of the source object. I attempted to store each property from the source object in an array, parse it, then see if each object element of the array includes it. However, this doesn’t take into account their values nor am I able to access each object specifically. At the moment I’m just parsing objects rather than their key/value pairs.

Your code so far

function whatIsInAName(objArr, sourceObj) {
  // const filteredArr = objArr.filter(element => element.hasOwnProperty);
  let filteredArr = [];
  let count = 0;

  /* for (let i = 0; i < objArr.length; i++) { 
    console.log("Object: " + i);
    count = 0;

    for (const element in objArr[i]) {
      console.log("Property: " + element + "\n" + "Value: " + sourceObj[element]);
      count++;
    }

    console.log("# of Key/Value Pairs: " + count);

    console.log("\n");
  } */

  // filteredArr = objArr.filter(element => helperFunction(objArr, element, sourceObj) === true);

  let sourceProperty = [];

  for (const element in sourceObj) {
    sourceProperty.push(element);
  }

  console.log(sourceProperty);

  // Unable to use for-loop or if-else statements in the callback function due to token error
  // .filter() takes 3 paramenters: current element, index of current element, and array it references
  // Attempted to use index value for the objArr to access the properties of each object
  filteredArr = sourceProperty.filter((element, index) => objArr[index].includes(element) === true);

  return filteredArr;
}

/* function helperFunction(objArr, objElement, sourceObj) {

} */

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

This line of code represents my latest attempt at trying to solve this lab, but I am stuck.

filteredArr = sourceProperty.filter((element, index) => objArr[index].includes(element) === true);

Challenge Information:

Implement a Matching Object Filter - Implement a Matching Object Filter

Hi @xSaberNight

First you’ll need to resolve the syntax error.

TypeError: objArr[index].includes is not a function

Happy coding

1 Like

Yeah, I went ahead and ensured it has a proper syntax. However, this approach leads me to a dead-end since it’s not technically validating the data. Only comparing the property names and extracting that value if they are.

  let sourceProperty = [];

  let objectProperty = [];




  // Store properties of sourceObj in array

  for (const element in sourceObj) {

    sourceProperty.push(element);

  }

  

  // Store properties of objArr in a seperate arraay

  for (const element of objArr) {

    for (const prop in element) {

      objectProperty.push(prop);

    }

  }

  

  console.log("Source Object Properties:");

  console.log(sourceProperty);

  console.log("\n");

  console.log("Object Properties:");

  console.log(objectProperty);




  filteredArr = sourceProperty.filter(element =>        objectProperty.includes(element) === true);

Function Call:

console.log("\nFunction Result:\n" + whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }));

Console Output:

Source Object Properties:
[ 'apple', 'bat' ]


Object Properties:
[ 'apple', 'bat', 'bat', 'apple', 'bat', 'cookie' ]

Function Result:
apple,bat

I am unsure on where to go from here or what direction to take for this Lab, as I am likely overcomplicating it.

Can you post the full code please? Easier to copy paste the entire thing to test it

1 Like

Yes, of course.

function whatIsInAName(objArr, sourceObj) {

  // const filteredArr = objArr.filter(element => element.hasOwnProperty);

  let filteredArr = [];

  let count = 0;


  /* for (let i = 0; i < objArr.length; i++) { 

    console.log("Object: " + i);

    count = 0;


    for (const element in objArr[i]) {

      console.log("Property: " + element + "\n" + "Value: " + sourceObj[element]);

      count++;

    }


    console.log("# of Key/Value Pairs: " + count);


    console.log("\n");

  } */


  // filteredArr = objArr.filter(element => helperFunction(objArr, element, sourceObj) === true);


  let sourceProperty = [];

  let objectProperty = [];


  // Store properties of sourceObj in array

  for (const element in sourceObj) {

    sourceProperty.push(element);

  }


  // Store properties of objArr in a seperate arraay

  for (const element of objArr) {

    for (const prop in element) {

      objectProperty.push(prop);

    }


  }


  console.log("Source Object Properties:");

  console.log(sourceProperty);

  console.log("\n");

  console.log("Object Properties:");

  console.log(objectProperty);


  filteredArr = sourceProperty.filter(element => objectProperty.includes(element) === true);

  return filteredArr;

}


/* function helperFunction(objArr, objElement, sourceObj) {


} */


console.log("\nFunction Call:\n" + whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }));

Waiting: 2. whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" }) should return [{ first: "Tybalt", last: "Capulet" }].

If I try this function call your function returns

[ 'last' ]

Can you explain in words, without implementation details, what your program will need to do, in steps?
1.
2.
3. etc

1 Like
  1. The function whatIsInName() is supposed to receive two arguments: an array of objects and a source object.
  2. The goal of the function is to return a new array of objects that contain the same key-value pairs as seen in the source object.
  3. If no objects from the array match the source object then the function should return an empty array.

NOTE: If the object from the array matches all key/value pairs from the source object, but has more key/values pairs, then it will still be accepted.

Example:

Object from array: [{ first: "Tybalt", last: "Capulet" }]

Source Object: { last: "Capulet" })

The object from the array has more key/value pairs, but it contains all key/value pairs from the source object so it is returned in the new array.

that describes the general requirements of the function

try writing detailed steps in describing what to do to compare the two objects

  1. iterate on the property of the object…
  2. check if the property…
  3. if true then…
  4. if false then…

and so on

1 Like

Ah, I see. I will do my best since I still haven’t found the right logic to utilize for this lab.

The main issue I am having is comparing the key/value pairs as a SINGLE entity rather than splitting the properties and values into two separate arrays to see if they are included in both the object element and source object. Or if there is a method to compare the object element as a whole that would also be suitable, but I don’t know how to implement that.

  1. Iterate over the array containing objects as its elements.

  2. Access the property within each element

  3. Compare the property within each element to the property of the source object

  4. If the two are equal then compare their key or value

  5. If the two are not equal then skip over that element.

  6. If the key/value is also equal then continue to parse over the rest of the key/value pairs for that object element.

  7. If ALL key/value pairs are equal and the object element contains ALL key/value pairs from the source object then extract it into a new array.

  8. If the key/value is not equal then skip over that element.

  9. After parsing every object element from the original array go ahead and return the new array.

  10. If no key/value pairs matched the source object then return an empty array.

1 Like

do you need to iterate over the array? can’t you access the object directly?

what do you mean if the two are equal? what kind of comparison are you doing? isn’t there a way to check if an object has a property that is simpler than this?

1 Like

Well, I wouldn’t know how many elements there will be in the array. Utilizing some form of loop to iterate over the array will ensure I am accounting for every object. Also to iterate over the object directly I would either have to reference its index or the object name, but it contained within an array without a name.

EX: for (const prop in objName) OR for (const prop in objArr[0])

If the object has a name such as:

const dog = {

name: “Sally”

};

I could then access it directly such as: for (const prop in dog)

As for what I meant in that step, I was checking if their property names are equal to each other.

EX: prop.name === sourceProp.name;

There is a simpler way to check if an object has a property, actually two I believe.

  1. hasOwnProperty() I believe is the proper syntax
  2. prop in object would be the alternative I think. ‘Prop’ being the property name itself and ‘object’ being the object name.

you are right, you have an array of objects to check

so try with more precise steps

  1. iterate over arrayOfObjects to access each object
  2. for each object inside arrayOfObjects:
    • iterate over…
1 Like

This is exactly the step we are doing now. Figure out the logic.

Then it will be much easier to implement.

1 Like
  1. Iterate over the array of objects, so that I can access each individual object.
  2. For each object inside the array, utilize the .hasOwnProperty()method to see if it includes the property from the source object.

NOTE: I won’t directly include this as a step since there may be fault in some logic, but this is the idea I currently have.

  • Utilize a for…in loop to parse over the properties of the source object which is nested within the loop used to iterate over the array of objects.
  • If the boolean value for the .hasOwnProperty()method is true then utilize a for…in loop to parse over the current element’s properties (from the array of objects).
  • Within the for…in loop utilize a condition to see if the value of the current property being parsed over in that object is equal to the value of the current property being parsed over in the source object.
  • If the two values are equal then push the object element from the array of objects into an array named newArray which will be used to return the array of objects that match.
  • If there are no matches then nothing will ever be pushed to the new array and an empty array will be returned.
const newArray = []; // Array to be returned

for (const element of objArr) {

     for (const prop in sourceObj) {

          if (element.hasOwnProperty(prop) === true) {

              for (const prop in element) {
                  if (element[prop] === sourceObj[prop]) {
                     newArray.push(element);
                  }
              }
          }

     }

}

I am aware that this Lab most likely expects a call-back function, but I had an idea in my mind and wanted to write it down before I forgot. So, using a .filter()callback function could also be employed which I can think of an approach for as well if the current one is faulty.

There is no such requirement. It would be written.

returns only those objects that match all key-value pairs in a given source object.

You should only push the object if ALL key-value pairs of the source match.

It seems your plan will push any object that has a single key-value match

Ah, that is true. Let me see…

const newArray = []; // Array to be returned
let elementMatch;

for (const prop in sourceObj) {

    for (const element of objArr) {

      elementMatch = false;

      if (element.hasOwnProperty(prop) === true) {

          for (const arrProp in element) {
              if (element[arrProp] === sourceObj[prop]) {
                 elementMatch = true;
              }
          }
      }
      if (elementMatch === true) {
         newArray.push(element);
      }
    }

}

So, I added a variable that stores a boolean value and also swapped the inner/outer loops at the top. At the end of the iteration of the loop that parses over the objects in the array of objects, it will only push that object into the new array if the elementMatch remains true. I ensured there is a reset for the variable’s boolean value for each iteration, so each element gets a chance.

Seems good? Did you try it out?

1 Like
function whatIsInAName(objArr, sourceObj) {

  const newArray = []; // Array to be returned

  let elementMatch;




  for (const prop in sourceObj) {

    for (const element of objArr) {

      elementMatch = false;




      if (element.hasOwnProperty(prop) === true) {

        for (const arrProp in element) {

          if (element[arrProp] === sourceObj[prop]) {

            elementMatch = true;

          }

        }

      }

      if (elementMatch === true) {

        newArray.push(element);

      }

    }

  }




  return newArray;

}




console.log("New Array:\n");

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

Console Output:

New Array:

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

For some reason, it seems to repeat the same object more than once in the new array.

use console.log inside your function to confirm whats happening

1 Like

Okay, I appear to be getting closer. The commented out code is my first iteration and the second iteration has me swapping around the for-loop declarations. I also added a for-loop name, so that I could break out of an iteration if the element from the object array doesn’t have the element from the source object. I had issues where it would just iterate again if it didn’t have it, get to the property it DOES have, and then the elementMatch was made true. So, something like ‘bat’ was being added if the source object was looking for ‘apple’ and ‘bat’.

function whatIsInAName(objArr, sourceObj) {

  const newArray = []; // Array to be returned

  let elementMatch;




  console.log("Array of Objects:");

  console.log(objArr);

  console.log("\nSource Object:");

  console.log(sourceObj);

  console.log("\n");





  // console.log("Elements Added to New Array:");




  /* for (const prop in sourceObj) {

    console.log("Current Source Obj. Property:");

    console.log(prop);

    console.log("\n");




    for (const element of objArr) {

      elementMatch = false;




      if (element.hasOwnProperty(prop) === true) {

        for (const arrProp in element) {

          if (element[arrProp] === sourceObj[prop]) {

            elementMatch = true;

          }

        }

      }

      if (elementMatch === true) {

        if (newArray.includes(element) === false) {

          console.log("Element being added to new array:");

          console.log(element);

          console.log("\n");




          newArray.push(element);

        }

      }

    }

  } */




  for (const element of objArr) {

    console.log("Current Object from Array:");

    console.log(element);

    console.log("\n");




    objectLoop: for (const prop in sourceObj) {

      elementMatch = false;




      for (const arrProp in element) {

        if (element.hasOwnProperty(prop) === true) {

          if (element[arrProp] === sourceObj[prop]) {

            elementMatch = true;

          }

        }

        else {

          break objectLoop;

        }

      }

    }




    if (elementMatch === true) {

      if (newArray.includes(element) === false) {

        console.log("Element being added to new array:");

        console.log(element);

        console.log("\n");

        

        newArray.push(element);

      }

    }

  }




  console.log("\n");




  return newArray;

}




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

Console Output:

Array of Objects:
[ { apple: 1, bat: 2 },
  { bat: 2 },
  { apple: 1, bat: 2, cookie: 2 } ]

Source Object:
{ apple: 1, bat: 2 }


Current Object from Array:
{ apple: 1, bat: 2 }


Element being added to new array:
{ apple: 1, bat: 2 }


Current Object from Array:
{ bat: 2 }


Current Object from Array:
{ apple: 1, bat: 2, cookie: 2 }


Element being added to new array:
{ apple: 1, bat: 2, cookie: 2 }




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

Now I’m only failing two test cases which account for empty arrays.