Intermediate Algorithm Scripting: Wherefore art thou - Confused

Intermediate Algorithm Scripting: Wherefore art thou - Confused
0

#1

Needless to say that I’ve spent two days trying to figure this out and I can’t get my head around it.
First the Object.keys was new and I read all I could on the subject but I still don’t understand it
Next, I’ve added in one of the three conditions that are still failing. This one is supposed to return [].
But the way I’ve written my code I’m still generating {object, Object] instead of an empty array.

Can anyone please explain this lesson and where I went wrong?

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var skeys = Object.keys(source);
  for (var i = 0; i < collection.length; i++){
    var j = skeys.length - 1;
    if (collection[i][skeys[j]] === source[skeys[j]]){
      arr.push(collection[i]);
    }
  }  
  console.log(arr);
  // Only change code above this line
  return arr;
}

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

https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou/


#2

The problem with your logic is you push collection[i] if the value of the last property/value pair of the collection[i] object matches any property/value pair of the source object.

Instead, you must make sure all of the property/value pairs of source are in each collection[i].

For example, in the following test case:

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

your function returns:

[ 
 { apple: 1, bat: 2 },
 { bat: 2 },
 { apple: 1, bat: 2, cookie: 2 } 
]

instead of:

[ 
 { apple: 1, bat: 2 },
 { apple: 1, bat: 2, cookie: 2 } 
]

UPDATE: I modified my reply above to correctly reflect what is happening in your existing code.


#3

Thanks
I’ll beat it to death for another day and get back to you :-s


#4

In the above line you are setting the value of j to be the same for every collection[i]. Part of the solution is changing j, so you are checking all sKeys and not just the the last one.


#5

I tried making j a for loop as well but I couldn’t work out how to build the result.
Well I abandoned the last code I just wasn’t getting it. So I tried a filter to sort out my keys but it still doesn’t work. I got it to work with a code solution which I’ve commented out but I want to work through this on my own.

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var skeys = Object.keys(source);
  /*return collection.filter(function(newCol){
    return skeys.map(function(key){
      return newCol.hasOwnProperty(key) && newCol[key] === source[key];
    })
    .reduce((a, b) => a && b);
  });*/
   return collection.filter(function(key){
     for (var i = 0; i < skeys.length; i++){
       if (key.hasOwnProperty(skeys[i]) || key[skeys[i]] === source[skeys[i]]){
         return true;
       }
       else return false;
     }
   });

  console.log(arr);
  // Only change code above this line
  return arr;
}

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

#6

I added some console.log statements to your code, so you can better see what is going on during execution.

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

   return collection.filter(function(key){
     for (var i = 0; i < skeys.length; i++){
       console.log('key = ' + JSON.stringify(key) +'\n')
       console.log('skeys['+i+'] = ' + skeys[i])
       console.log('key[skeys['+i+']] = ' + key[skeys[i]])
       console.log('source[skeys['+i+']] = ' + source[skeys[i]])
       if (key.hasOwnProperty(skeys[i]) || key[skeys[i]] === source[skeys[i]]){
         console.log(true)
         return true;
       }
       else {
         console.log(false)
         return false;
       }
     }
     console.log()
   });

  console.log(arr);
  // Only change code above this line
  return arr;
}

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

/* above code displays the following to the console

key = {"a":1,"b":2,"c":3}

skeys[0] = a
key[skeys[0]] = 1
source[skeys[0]] = 1
true

*/

and the function returns [ { a: 1, b: 2, c: 3 } ]


#7

Thanks
When sKeys[1] = b shouldn’t it fail since key[sKeys[1]] and source[keys[1]] are not equal?
I’m passing the first three tests when I changed the || to && but the last three tests fail


#8

|| means OR and && means AND. Only one condition has to be true with || and both have to be true with &&.


#9

Yes thanks
When I changed it I passed the first test as well as the second two but I’m still failing on the last three
So both conditions are required to pass the test for hasOwnProperty
I don’t get why I’m returning collection and not comparing with source?


#10

Well…after three days I checked the solutions and found one that does pretty much the same as mine but it checks for the keys and properties don’t match. At least I learned a lot of new functions, hopefully the next test is more straightforward.

Thanks Randell for your help

Final code:

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var sKeys = Object.keys(source);
  /*return collection.filter(function(newCol){
    return skeys.map(function(key){
      return newCol.hasOwnProperty(key) && newCol[key] === source[key];
    })
    .reduce((a, b) => a && b);
  });*/
  return collection.filter(function(key){
     for (var i = 0; i < sKeys.length; i++){
       if (!key.hasOwnProperty(sKeys[i]) || key[sKeys[i]] !== source[sKeys[i]]){
         return false;
        }
       }
       return true;
     
   });

   /*return collection.filter(function (key) {
    for(var i = 0; i < sKeys.length; i++) {
      if(!key.hasOwnProperty(sKeys[i]) || key[sKeys[i]] !== source[sKeys[i]]) {
        return false;
      }
    }
    return true;
  });*/

  console.log(arr);
  // Only change code above this line
  return arr;
}

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