What needs to be improved in this code to make it work?

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


for (let i = 0; i < collection.length; i++) { 
  for(let y = 0; y < keysa.length; y++) {
  if(collection[i].hasOwnProperty(keysa[y]) && collection[i][keysa[y]] === source[keysa[y]]) {
      arr.push(collection[i]);
    }

  }
}
return arr;
} 

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

Desafío: Donde estás

Look at the one that is failing and try to figure out why. Put in log statements to trace through and see why your logic isn’t doing what is needed.

I really don’t know what’s wrong

Again, just simple observation, when I look at the tests that are passing and the tests that are failing… all the ones that are passing have something in common and all the ones that are failing have something in common. Hint: Look at the second parameter.

Next, when I look at the first failing test:

whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }) should return [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }] .

I put that into the code and run it. I also put some log statements into the code to see what is happening:

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

  for (let i = 0; i < collection.length; i++) { 
    console.log('\n* starting i loop', i, collection[i])
    for(let y = 0; y < keysa.length; y++) {
      console.log('*** starting y loop', y, keysa[y])
      if(collection[i].hasOwnProperty(keysa[y]) && collection[i][keysa[y]] === source[keysa[y]]) {
        console.log('***** match found, pushing', collection[i])
        arr.push(collection[i]);
        console.log('***** arr after push:\n', arr)
      }
    }
  }
  return arr;
} 

console.log('\n\nfinal answer\n', whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }));

Run that and see if that helps you understand what is wrong. Trace through - think about should happen and see what is happening. Often it is good to think through the algorithm, not even thinking about code. Think about how you would explain how to do this to a person who had no intuition, but had to be given a methodical approach to solve this.

A good programmer is a good debugger. And a good debugger is a good detective.

thank you very much, I got what is wrong, every time it finds a single match it pushes it, the iteration is not in block on the match, which leads me to think that for loops are wrong so I see I should use filter but I thought I could use a basic for loop for this, is there much difference between the two if you want to achieve the same thing? (sorry for my English, hope it’s understood)

There is nothing you can do with filter that you can’t do with for. filter is just a loop with the mechanics hidden in a function/method. In fact, since you have more control, sometimes a for loop can do things that filter can’t. The nice thing is that filter is cleaner. My instinct is that you should know how to solve it with for before you try the prototype methods.

I think you just need to adjust your thinking of the logic of when to push.

I managed to pass it although I’m sure it wasn’t what you wanted me to do haha, what do you think of this code? although it passes the tests I would have liked to use push() and I couldn’t not use the filter in the end

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

 for (let i = 0; i < collection.length; i++) { 
    console.log('\n* inicio bluce i: ', i, collection[i])
    
    for(let y = 0; y < keysa.length; y++) {     console.log('*** inicio bluce y: ', y, keysa[y])
    
    if(!collection[i].hasOwnProperty(keysa[y])||collection[i][keysa[y]] !== source[keysa[y]]) {
      
      console.log('***** coincidencia encontrada, push: ', collection[i])
     delete arr[i];
    console.log('***** arr después del push push:\n', arr)
      
       }    
    }
  }

return arr.filter((item) => item !== null);

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

I wrapped your code in [spoiler][/spoiler] tags since it is a working solution to a challenge.

I would have liked to use push()

You 100% can. I mean, you came up with a solution. It’s a little clunky, but hey, you’re still learning so take whatever victories you can get. A lot of people have trouble on this one.

The problem with what you were doing with push was the logic.

Hint:

The issue was your logic. You were pushing the value onto the array whenever there was a match. This would work fine if the source only had one key/value pair. But if it has more than one, you were pushing on for every match. Not only do you only want to push on only once, you only want to do it if all the key/values match.

This was your pseudocode:

loop over collection
  loop over keys
    if match found
      push onto arr

But you needed something more like this:

loop over collection
  set nonmatch flag false
  loop over keys
    if nonmatch found
      set nonmatch flag true
      break loop
  if nonmatch is false
    push onto arr
1 Like