Can't return all the 'true' element of an array

Can't return all the 'true' element of an array
0.0 0

#1

Hello,

I’ve been stuck badly on an intermediate challenge: Wherefore art thou

I am doing it step by step, but I can return in the console what I want.
I think my script is right, as it return “true” if I select the array element that I am testing, and “false” if the element doesn’t meet the requirement of the if.
However, I can print in the console all the element that are true, only the last one.

Can you please help me? I know this won’t be the end of the challenge, but if I can at least print this result, i will be able to move forward to hopefully complete it.

here is my code:


function whatIsInAName(collection, source) {
  
var key = Object.keys(source);
var test = [];

for (var i = 0; i < collection.length; i++){
  for (var x = 0; x < key.length; x++){
    if (collection[i].hasOwnProperty(key[x])){
      test = collection[i];
    }

  } 
}
  
return test;
}

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

Thank you!


#2

Your line:

test = collection[i];

is causing test to only contain the very last instance when collection[i].hasOwnProperty(key[x]) is true. You keep overwriting test’s value anytime a particular collection object contains one of the source properties. The last value of test is what the function returns.


#3

Thank you Randell,

i figured this, but I don’t know how to assign all the true element only to test. i tried numerous thing, but couldn’t get one to work.

Do you know what would be the way to return all the true elements only?!

Thank you.


#4

Absolutely, but it would be better if you could figure out a solution on your own. You should already know how to push values into an array. If not, then review the following FCC challenge.

Your current solution is only checking if any of the source properties exist in a particular collection object. You should only being added elements to test if all of the source properties exist and the collection object properties have the same values as the source properties. You are missing a bit more logic to accomplish that.

I suggest writing out an algorithm on paper or type it up in plain language. The algorithm will be all the steps including checks (if conditions) needed to assure you only add objects which contain each source properties values. Once you have written something down on paper, try to walk through one of the test cases, to see if your written algorithm would return an array containing that applicable objects.

Only once you think you have the correct algorithm, should you attempt to write any JavaScript code for your solution.


#5

Hello Randell,

First of all, thank you very much for your answers. I did try the push() yesterday, but still couldn’t get the expected result.

I tried to keep working on this yesterday, and this morning too. I can see that my script can define what is true or false, but I can’t find a way to only show what is true…

At this point, i am just trying to send to test if the all the source properties exist in a particular collection object. Once I succeed to pass this phase, I will take care of the values of the properties.

Here is what I came up with:

function whatIsInAName(collection, source) {
  
var key = Object.keys(source);
var test = [];

for (var i = 0; i < collection.length; i++){
  for (var x = 0; x < key.length; x++){
    if (collection[i].hasOwnProperty(key[x])){
      test.push(collection[i]);
    }
else {
  test.push("no");
     }
   } 
}
return test;
}

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

In the console, I can see that the second element of the first object doesn’t pass the true thanks to the “no” coming right after. My struggle is how to not send it to test if it is false?

If i wrote the code like this:

function whatIsInAName(collection, source) {
  
var key = Object.keys(source);
var test = [];

for (var i = 0; i < collection.length; i++){
  for (var x = 0; x < key.length; x++){
    if (collection[i].hasOwnProperty(key[0]) && collection[i].hasOwnProperty(key[1])){
      test.push(collection[i]);
    }
else {
  test.push();
     }
   } 
}
return test;
}

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

I get the outcome that I’m looking for, but this is not the right practice.

What logic am I missing in my first script? From my reasoning, the script should be working, but it is obviously not! So I’m stuck here and can’t think of an other way to approach this issue at this point. Why does my script doesn’t only return the “true” ?!

Thank you


#6

Let’s work through the test case with your code.

The outer for loop starts with i = 0

In the first iteration of the inner for loop, x = 0, so your code checks if {“a”:1,“b”:2} has the property “a”. It does, so you add {“a”:1,“b”:2} to test.

In the second iteration of the inner for loop, x = 1, so your code checks if {“a”:1,“b”:2} has the property “b”. It does, so you add {“a”:1,“b”:2} to test.

The outer for loop now has i = 1

In the first iteration of the inner for loop, x = 0, so your code checks if {“a”:1} has property “a”. It does, so you add {“a”:1} to test.

In the second iteration of the inner for loop, x = 1, so your code checks if {“a”:1} has the property “b”. It does NOT, so you add “no” to test.

The outer for loop now has i = 2

In the first iteration of the inner for loop, x = 0, so your code checks if {“a”:1,“b”:2,“c”:2} has property “a”. It does, so you add {“a”:1,“b”:2,“c”:2} to test.

In the second iteration of the inner for loop, x = 1, so your code checks if {“a”:1,“b”:2,“c”:2} has the property “b”. It does, so you add {“a”:1,“b”:2,“c”:2} to test.

Your algorithm is only looking at each source property to see if it is in the current collection object being checked. Your solution is not keeping track whether or not ALL the source properties are in the current collection object being checked.

Like I said before, you need to write out your algorithm and walk through the code like I just did above, to prove out your algorithm works or does not work. You do not have to write full code for your algorithm steps. It can be plain language or a mix of plain language and code. The logic still has to work though.

I will give you something to think about for at least helping to identify if you should consider adding a collection object based strictly on the property name. You could create another variable (let’s call it propFound) before the inner for loop and assign the value of true to this variable. The reason you would assign it true, is you would be assuming that all of the source properties will be found. Then, inside the inner for loop, your code would need to check if the current source property does NOT exist in the current collection object. If the if statement evaluates to true (meaning the property does not exist), then you assign the value of false to the propFound variable and then break out of the inner for loop. The break will prevent any other source property from being checked. Just outside the inner for loop, you would check if propFound is true. If it is still true, that means all the source properties where found in the current collection object, so you should push the object to test. If not, do nothing.


#7

Thank you for the very detailed answer! This should be very helpful. This is the logic that I need to get.

I will get back at it trying to figure it out with your explanation.


#8

Hello Randell,

I just wanted to share with you the final script that I came up with thanks with your help.
This one is working and passed the challenge.

function whatIsInAName(collection, source) {
  // What's in a name?
var key = Object.keys(source);
var test = [];
var arr = [];

for (var i = 0; i < collection.length; i++){
  var propFound = true;
  for (var x = 0; x < key.length; x++){
    if (!collection[i].hasOwnProperty(key[x])){
      propFound = false;
      break;
    }
   } 
  if (propFound === true){
      test.push(collection[i]);
    }
}
  
  for (var z = 0; z < test.length; z++){
    var valFound = true;
    for (var j = 0; j < key.length; j++){
      if (test[z][key[j]] !== source[key[j]]){
        valFound = false;
        break;
    }
  }
    if (valFound === true){
      arr.push(test[z]);
    }
    }
return arr;
}

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

However, I still have to study this one to fully understand how the script works (to many tries make you lost track!). I am going to try now to make this shorter as well.

Thanks for your help! much appreciated.


#9

That is why you write an algorithm first, before you try coding it. If the algorithm meets the challenge requirements, then the code you write will make more sense to you.

My recommendation to you is click the Reset your code button for this challenge and now that you have a better idea how to approach it, try documenting your algorithm before writing your second version of a solution.