Intermediate Algorithm Scripting: Wherefore art thou(Help!)

So I created a loop to go over the collection array and a loop for the new array I created with Object.keys, for the source argument. The code is supposed to go over each item in the collection array and check to see if it contains anything from the source array which is also being looped through. I feel like the problem here is that my code is only reviewing the keys and not the values of those keys(entries). How do I make this code go a layer deeper and check the entries as well. Or is there another issue as well?


function whatIsInAName(collection, source) {
var arr = [];
source=Object.keys(source)
let a=0
// Only change code below this line
for(let i=0;i<collection.length;i++) {
  for(let j=0;j<source.length;j++){
if (collection[i].hasOwnProperty(source[j])===true) {
  a=collection[i]
  arr.push(a)
}
  
}

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

}

console.log(whatIsInAName([{"a": 1, "b": 2, "c": 3}], {"a": 1, "b": 9999, "c": 3}));

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36.

Challenge: Wherefore art thou

Link to the challenge:

Hi annonbubble!

At first glance, you are on the right path! But currently, you are only checking if the property matches, not the value. So you could extend the if to also check the value.

Cheers
Tom

2 Likes

In addition to @TomDeS’s advice, you’ll want to avoid what you’re doing above. You’re effectively getting rid of the reference to the source object by reassigning source with the return value from Object.keys. Use a separate variable for the keys and you’ll be closer to being able to solve it.

2 Likes

Hi, looks like you’re going down the same path as me. Here’s what I’ve got so far:

let sourceKeys=Object.keys(source); //pull keys out of "source"
  for (let i=0;i<collection.length;i++){ //loop through each object in "collection"
    for (let j=0;j<sourceKeys.length;j++){ //loop through each key in "sourceKeys"
      if (collection[i].sourceKeys[j]===source.sourceKeys[j]){ //check for matches
        arr.push(collection[i]); //push matches to return array
      };
    };
  };

I’m not quite there yet, I’m getting this error which has me confused:
TypeError: Cannot read property ‘0’ of undefined
(EDIT: needed to use bracket notation instead of dot notation! i.e.
collection[i][sourceKeys[j]]
)

Plus this will only return single matches, it won’t require that ALL matches are present (still some work to do on that front).

If I log out the elements separately they all look correct but don’t seem to want to play together:
sourceKeys[j] = "last"
collection[i].last = "Montague" (etc).
collection[i].sourceKeys[j] = [TypeError]

I think I’ve got the right jigsaw pieces, I just need to figure out how they fit together. Hope something here helps, keep at it (you’re not alone!).

1 Like

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

1 Like

I have tried using Object.entries but that just creates nested arrays. Cannot seem to figure out how to check those values as I have nothing to refer to them to.

Hi AnonBubble,

With this bit of your code:

if (collection[i].hasOwnProperty(source[j])===true) {
  a=collection[i]
  arr.push(a)
}

it will only check that the key exists, not that the values are the same. Using the example in the lesson, your code is asking
“does this object have a key named ‘last’?”
instead of
“does this object have a ‘last’ value of ‘Capulet’?”.

To do that you’d need something like:

  // Only change code below this line
  let sourceKeys=Object.keys(source);
  for (let i=0;i<collection.length;i++){
    let trueFalse=[];
    for (let j=0;j<sourceKeys.length;j++){
      if (collection[i][sourceKeys[j]]===source[sourceKeys[j]]){ // << HERE!!
        trueFalse.push(true);
      } else {
        trueFalse.push(false);
      };
    };
    if (trueFalse.every(truth=>truth===true)){
      arr.push(collection[i]);
    };
  };
  // Only change code above this line

(I had a eureka moment overnight with the trueFalse tracker array! :laughing: That was the missing piece for me).

Like I say, keep at it. Feeling confused just means you’re learning :+1:

1 Like

It is great that you solved the challenge, but instead of posting your full working solution, it is best to stay focused on answering the original poster’s question(s) and help guide them with hints and suggestions to solve their own issues with the challenge.

We are trying to cut back on the number of spoiler solutions found on the forum and instead focus on helping other campers with their questions and definitely not posting full working solutions.

You can post solutions that invite discussion (like asking how the solution works, or asking about certain parts of the solution). But please don’t just post your solution for the sake of sharing it.
If you post a full passing solution to a challenge and have questions about it, please surround it with [spoiler] and [/spoiler] tags on the line above and below your solution code.

1 Like

I am still stuck on that same if statement line. I cannot seem to figure out how to edit that if statement to check the value of the property as well. Is it because I used Object.keys?

Indeed that is part of the issue. Personally I find it useful to add a console.log when I am stuck. For example like this:


You see how the yellow marked still has both the keys and the values? After you do source = Object.keys(source), you lose the values so you cannot check those anymore in the if statement.

So what is the point of using Object.keys if it just deletes the entries? I have also tried using object.keys(source) in a different variable, and used that variable
and no luck


  var arr = [];

  let key=Object.keys(source)

  let a=0

  // Only change code below this line

  for(let i=0;i<collection.length;i++) {

    for(let j=0;j<key.length;j++){

  if (collection[i].hasOwnProperty(key[j])) {

   

    a=collection[i]

    arr.push(a)

  }

     console.log(key[j])

  }

  

  }

return arr;

  // Only change code above this line

}

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

You are really close to a solution :wink:

The issue you are having now is this: source = Object.keys(source). Doing so throws away the values of the source array. But since you have to compare both the key and the value, you cannot throw away the value.

So a possible solution (remember that there are often multiple ways to the same result) could be to use two variables. In one you store the the keys (as you did here: let key=Object.keys(source)). And then you can use the original array to compare the value. Remember that you can use the key array to know which values you have to compare.

How does that sound to you, does it make the issue more clear? If not, we are here to help :wink:

1 Like

I tried
if (collection[i].hasOwnProperty(key[j])&&key[j].hasOwnProperty(source[key])===true) {
This challenge is kicking me lol, idk why it won’t click. I know why the issue is happening but I cannot apply the changes I want. I know source[key] is where is value is but it’s not reading that value either

key[j] is a string, and key is an array - you may need to review this part, as you need to use hasOwnProperty on an object, and pass in the property to check

1 Like

so I need to turn key[j] into an array/object?

no, you need to consider what you want to check, and if you think that hasOwnProperty is the best way to do it, also what object you use it on, and what string you put in as argument

1 Like