Wherefore art thou trouble

Wherefore art thou trouble
0.0 0

#1

Tell us what’s happening:
I’m having trouble checking for the values when there are multiple property/value pairs being passed through as “source”. Any help with this would be appreciated.

Your code so far

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var val = [];
  var thing = Object.keys(source);
  collection.forEach(function (item){
    for (i=0; i<thing.length; i++){
      if (item.hasOwnProperty(thing[i]) && item[thing[i]] == source[thing[i]]){
        arr.push(item);
      }
    }
  });
  // Only change code above this line
  return arr;
}

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

Your browser information:

Your Browser User Agent is: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36.

Link to the challenge:


#2

The problem with your current logic, is that it adds an entire collection obj (item) to arr for each source property which exists in item and where the values match. You only want to add item when every source property is in item and every matching source property value is equal to the item property’s value.

If you had an extra variable (a Boolean of true or false) which kept track if all source properties and their corresponding values matched during any given iteration of the for loop, then as soon as a source property either was not present in item or the source property value did not match the item property’s value, you could assign this variable the value false and break out of the for loop. If this extra variable started with a value of true, then after the for loop ended or was broken out of (see explanation above), then your code should only add item if this extra variable had a value of true.


#3

Thanks! This is my implementation of your suggestion and it works!

function whatIsInAName(collection, source) {
// What’s in a name?
var arr = [];
// Only change code below this line
var val;
var thing = Object.keys(source);
collection.forEach(function (item){
for (i=0; i<thing.length; i++){
if (item.hasOwnProperty(thing[i]) && item[thing[i]] == source[thing[i]]){
val = true;
}else {
val = false;
}
}
if (val == true){
arr.push(item);
}
});
// Only change code above this line
return arr;
}

whatIsInAName([{ “a”: 1, “b”: 2 }, { “a”: 1 }, { “a”: 1, “b”: 2, “c”: 2 }], { “a”: 1, “b”: 2 });


#4

Your solution passes FCC tests, but it is because coincidentally the last source property/value matches an item. Your solution does not actually do what I recommended. For example, if you had the following case, it should return an empty array, because the source property ‘z’ does not exist in any collection object. Your solution returns [ { a: 1, b: 2 }, { a: 1, b: 2, c: 2 } ], because your solution only cares about the last value of val after the for loop has ended. Even though at some point in the for loop iterations, val is false, you overwrite it with a true if the last source property is a match.

whatIsInAName([{ a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 }], { z: 1, b: 2 }); // should return [ ]

#5

You know, that’s making me wonder if any of my other algorithm solutions are just coincidentally working as well. I updated my code and added your objects. Does that fully accomplish what you were recommending?

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var val;
  var thing = Object.keys(source);
  collection.forEach(function (item){
    for (i=0; i<thing.length; i++){
      if (item.hasOwnProperty(thing[i]) && item[thing[i]] == source[thing[i]]){
        val = true;
      }else {
        val = false;
        break; //the new part
      }
    }
   if (val == true){
        arr.push(item);
   } 
  });
  // Only change code above this line
  return arr;
}

whatIsInAName([{ a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 }], { z: 1, b: 2 });


#6

This new solution is more like what I was saying and accomplishes what the challenge should be testing for. Congrats on writing a more robust function!

You could actually initialize val as true before the for loop and then just look for the case where the source property does not exist in item OR source property value does not match the item’s property value. See my comments in the code below.

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line

  var thing = Object.keys(source);
  collection.forEach(function (item){
    var val = true; // assumes current collection object (item) will be added
    for (i=0; i<thing.length; i++){
      if ( !item.hasOwnProperty(thing[i]) || item[thing[i]] !== source[thing[i]] ){
        val = false; // was not found or did not match
        break; // stop for loop because item should not be added to arr
      }
    }
   if (val == true){
        arr.push(item);
   } 
  });
  // Only change code above this line
  return arr;
}