Wherefore art Thou - stuck for a while now

Hey guys, so I’ve been stuck in this challenge for a while now, I feel like I’m overthinking it and doing some crazy methods which led to this crazy code I got right now.
I managed to pass all the tests but one when I realized I was comparing only the values of the keys and not both the keys and values, but I have no idea on how to do that, as getting the key’s values was hard enough.
Can anyone shed some light here? I wanted to make it with this code since I worked some good hours on it, even though it seems messy. It has some console.logs to help me keep track of things. Appreciate any kind of help, even if you tell me to just scratch it all off and start fresh.

Here it comes

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  var sourceLength = Object.keys(arguments[1]).length;
  console.log(sourceLength);
  // Only change code below this line
  for(let i = 0; i < arguments[0].length; i++){
    console.log(`this is object index ${i}`);
    let counter = 0;
    for(var propName in arguments[0][i]) {
    if(arguments[0][i].hasOwnProperty(propName)) {
        var propValue = arguments[0][i][propName];
        console.log(propValue + ` this is propValue`);
    }
    for(var propName in arguments[1]) {
    if(arguments[1].hasOwnProperty(propName)) {
        var sourceValue = arguments[1][propName];
        console.log(sourceValue + ` this is sourceValue`); 
        if (propValue === sourceValue){
          counter++;
          console.log(counter + ` this is the counter`);
        }  
               
    }
  }

    }
  if (counter >= sourceLength){
    arr = arr.concat(arguments[0][i]);
    console.log(arr + ` this is arr`);
  }
  console.log(`ending object index ${i}`);
  }
  
  // Only change code above this line
  return arr;
}

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

You can use Object.getOwnPropertyNames() to return the keys for the source.

for(var propName in arguments[0][i]) {
  // do stuff
  for(var propName in arguments[1]) {
    // and now we have overwritten previous propName :( 
  }
}

After you fix that it’s pretty simple to compare both keys and values.

1 Like

Writting a pseudo code is extremely useful for you and for us as well, because if there’s something specific you want to do but don’t know how to (like getting all the properties of an object), then people can direct you to the right path.

So in your opinion, what is the first problem you have to solve in order to complete this challenge? Ask that yourself, this way things start to make more sense and you might be able to come up with the solution by yourself.

For example, why do you think you need this var sourceLength = Object.keys(arguments[1]).length;, what are you trying to solve or do with it?

I recently went through this challenge and it was hard, I think I spent a total of 10 hours or so trying to solve it.

1 Like

Appreciate the answer!
So yeah, this var sourceLength = Object.keys(arguments[1]).length; thing goes along with the counter in both

 if (propValue === sourceValue){
          counter++;
          console.log(counter + ` this is the counter`); 

and

if (propValue === sourceValue){
         counter++;
         console.log(counter + ` this is the counter`); 

I did this so the arguments[0][i] would only concat with arr once all the objects in source were confirmed to be inside arguments[0][i]. But I have to say, this didn’t feel like the best solution, I thought it was doing the job.

The most important thing I think I’m missing is that the code doesn’t check for same key names, only values, which means object { "apple": 1, "bat": 2 } gets concatenated in arr because it shares the same values, in the same order, as source { "apple": 1, "cookie": 2 }.

I’m not sure I follow this tip, because the code as it is checks for the props in the correct order, while it’s inside one another’s for loop. I changed the var declaration to a let, but I haven’t seen no difference, would you mind expanding on this?

You said you want to compare not only values, but also key names (i.e. propName in outer loop with…:thinking:)

1 Like

You are a god. This was incredibly simple really. This is what I want to say is my final code, passing all the tests.

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  var sourceLength = Object.keys(arguments[1]).length;
  console.log(sourceLength);
  // Only change code below this line
  for(let i = 0; i < arguments[0].length; i++){
    console.log(`this is object index ${i}`);
    let counter = 0;
    for(var propName in arguments[0][i]) {
    if(arguments[0][i].hasOwnProperty(propName)) {
        var propValue = arguments[0][i][propName];
        console.log(propValue + ` this is propValue`);
    }
    for(var sourceName in arguments[1]) {
    if(arguments[1].hasOwnProperty(sourceName)) {
        var sourceValue = arguments[1][sourceName];
        console.log(sourceValue + ` this is sourceValue`); 
        if (propValue === sourceValue && propName === sourceName){
          counter++;
          console.log(counter + ` this is the counter`);
        }  
               
    }
  }

    }
  if (counter >= sourceLength){
    arr = arr.concat(arguments[0][i]);
    console.log(arr + ` this is arr`);
  }
  console.log(`ending object index ${i}`);
  }
  
  // Only change code above this line
  return arr;
}

The important thing was to change the second “propName” to “sourceName” and compare it in:

 if (propValue === sourceValue && propName === sourceName){
          counter++;
          console.log(counter + ` this is the counter`);
        }  

I asked you what’s the purpose of this line of code here var sourceLength = Object.keys(arguments[1]).length, it would seem you are trying to get all the properties of the source object in an array and then you want to use the length of that array to do some other stuff, that’s fine.

So the question you should ask yourself is: How to get all the properties of an object? You type that on Google and you will find different answers, you are already using a method that solve that problem

However you are doing some extra work for no reason at all (I think)

This Object.keys(arguments[1]).length could be easily be translated to this Object.keys(source).length, you get the same result but the latter is cleaner and less confusing, it’s just easier to understand.

You can apply this logic for the rest of your code.

1 Like

Functional approach (it’s an intermediate algorithm after all):

function whatIsInAName(collection, source) {
  return collection.filter(s =>
    Object.keys(source).every(k => source[k] === s[k])
  );
}

#showoff

1 Like

You’re absolutely right, I had just worked with the arguments object and my (VERY) frustrated mind at the point found it easier to work with for the time being. I’ve cleaned the code right now using the collection and source arguments.

ROFL. I was absolutely sure I should have used at least the filter method, but I got really frustrated on how to work with object keys, i couldn’t get myself to get it right when using filter() and whatnot.
I got really frustrated and my mind got blocked. I stood staring at the screen for at least a couple of hours without getting anything done, once I got something going with all these overlapping if and for loops I decided to stick with it. Your solution looks awesome though! And it’s not hard to understand at all. Really appreciate your help guys!