Why does the code for beginner wherefor art thou solution work?

Why does the code for beginner wherefor art thou solution work?
0

#1

beginner solution:

function whatIsInAName(collection, source) {
  // "What's in a name? that which we call a rose
  // By any other name would smell as sweet.”
  // -- by William Shakespeare, Romeo and Juliet
  var srcKeys = Object.keys(source);

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

The tricky part about this algorithm is that all of the properties in source have to be in each member of collection that you return. So, how does this code do that part? Also, how does the “return true” statement after the for loop not override the for loop’s output? In other words, I can’t tell the difference between the code above and code below:

function whatIsInAName2(collection, source) {
  // "What's in a name? that which we call a rose
  // By any other name would smell as sweet.”
  // -- by William Shakespeare, Romeo and Juliet
  var srcKeys = Object.keys(source);

  // filter the collection
  return collection.filter(function (obj) {
    for(var i = 0; i < srcKeys.length; i++) {
      return !obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i]] !== source[srcKeys[i]] ? false : true
    }
  });
}

How the two intermediate solutions work is obvious to me, but this works is not obvious, and I clearly don’t understand something fundamental about js

edit: to be more clear about the differneces between the code:

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

whatIsInAName2([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 })
outputs:
[ { a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 } ]

further edit: I know what a ternary operator is, and even if you turn the ternary operator in my second example into an if/else statement, the function’s output is not correct. I know why the output is not correct. I don’t know why the first, official beginner’s solution to the algorithm question, is correct. The way that it meets this: “Each property and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.” requirement.

Also, I know that the return true statement is in different places. That’s the point.


#2
if (!obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i] !== source[src[Keys[i] {
  return false;
}

This line checks to see if Object you are checking has the same keys as the source Object or if the Object does have the key if that key holds the same value as it does in the source Object.

If either of these is are not true the code returns false.

In the second example it is done the exact same way but they use the ternary operator.

return !obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i] !== source[srcKeys[i] ? false : true

This will return false if the condition that is in between “return” and the “?” is true (which means we encountered and object that doesn’t have the same key as the source or if the Object has the same key but the key holds a different value. It’s just shorthand for the same conditions.


#3

I’ve edited your post for readability. When you enter a code block into the forum, remember to precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.


#4

It doesn’t do the exact same thing, the two functions return different two different outputs. The second checks if the each individual key of source is in obj of collection, but it does not check if obj of collection is a superset of source


#7

@Machiner123

Sorry after you edited your post I went back and looked it’s because you need to edit your if condition to have an else statement that returns true, not wait until the entire loop is done and then return true. I didn’t realize the “return true” was outside of the loop and that’s why the conditions don’t match.

Therefore the first one should look like this:

function whatIsInAName(collection, source) {
// "What's in a name? that which we call a rose
// By any other name would smell as sweet.”
// -- by William Shakespeare, Romeo and Juliet
var srcKeys = Object.keys(source);

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

#8

I like you because you’re trying, but can you try to run your code before you post it and try to understand the actual question


#9

To be fair someone had to come in and format your post because it was not easily understandable, then after that, you went and had to make more edits on top of it. I’m glad you appreciate that I’m trying to help but put more effort into your post and these kinds of issues go away.


#10

Ironies of ironies: I edited the post to make it clear to you that the two functions have different outputs, which should have been obvious, but I didn’t want to discourage you. I still don’t. So, I will put a further edit to clarify that I know what a ternary operator is.


#11

Again, you edited it because it wasn’t clear. Not really trying to argue about it, I figured out why the code wasn’t working how you desired it to work. The return true statement was in the wrong place. That answers the question so not sure how any of this is ironic but like I said in order to avoid it in the future maybe just format your post from the beginning when looking for input from others.


#12

You don’t know why it works, you just know that it works


#13

This isn’t true. In the second solution, the ternary operator returns true or false every iteration. The way you had the code set up in the first example it returns false or nothing every iteration. It can only return true at the very end because the return true statement is outside of the for loop itself. I explained this in my solution to your problem.

You lecture me about reading and understanding and then say I don’t know what I’m talking about which indicates you’re not willing to do what you require of others. I found the solution and explained it. Other than that I don’t know what more else you want other than to be upset because I had a hard time deciphering a sloppy post.

This isn’t even about code anymore so have a good one wish you luck on your coding journey.


#14

I figured it out. If there are two return statements, javascript ignores the second.

function whatIsInAName(collection, source) {
  // "What's in a name? that which we call a rose
  // By any other name would smell as sweet.”
  // -- by William Shakespeare, Romeo and Juliet
  var srcKeys = Object.keys(source);

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

function whatIsInAName2(collection, source) {
  // "What's in a name? that which we call a rose
  // By any other name would smell as sweet.”
  // -- by William Shakespeare, Romeo and Juliet
  var srcKeys = Object.keys(source);

  // filter the collection
  return collection.filter(function (obj) {
    for(var i = 0; i < srcKeys.length; i++) {
      return !obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i]] !== source[srcKeys[i]] ? false : true
    }
  });
}


// This doesn't return true fpr {"a":1} because it compared it to {"b":2} and returned false for that whole loop through source, so {a:1} gets filtered out of arr
whatIsInAName([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 })
output: [ { a: 1, b: 2 }, { a: 1, b: 2, c: 2 } ]

// This returns true for {"a": 1} because we ask it to check, and so  { a: 1} is included in arr
whatIsInAName2([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 })
output: [ { a: 1, b: 2 }, { a: 1}, { a: 1, b: 2, c: 2 } ]
'''

#15

This is technically true, but does not describe how the algorithm is working and it doesn’t answer your question.

The difference between the two is simple. A return statement inside of a loop will exit the loop and the function. You need an if clause inside of the loop, otherwise it will not iterate. whatIsInAName does this because it uses the if clause to check whether it should return false. whatIsInAName2 always returns a value before i ever increments. Because this value happens to be true with the data you provide, whatIsInAName2 outputs the collection without filtering anything. So, when a function contains multiple return statements, the function will take the first one it comes to and all code after that point is not evaluated. However, it’s not true that JavaScript unconditionally ignored any return statements after the first.

function doAThing(num) {
    if(num > 5) {
        return true; // only reached if num > 5
    }
    return "Hippos";  // only reached if num < 5, otherwise not evaluated
}

function dontDoAThing(num) {
  return true; // the function will always end here, no matter what

  var newNum = num + 1000; // All of the following code is not evaluated

  return newNum;
}

A note on decorum - please refrain from antagonistic comments. Statements like

are childish and unnecessary.


#16

Your explanation is much better than mine (can be found in comments right above the output in the code I included in explanation). I stand by what I said to iamknox, he even lied in one of this posts because I tried his code and it didn’t run.


#17

I definitely didn’t lie @machiner123 and if you actually tried out my code, I went back and deleted those posts because there was a copy paste error (which was clearly visible in the screenshot of code you claim you tried out) when I was taking the code you posted. This resulted in me initially getting the same results. I even apologized when I went back and retackled your problem which can be seen above. Your code produced different results because of where your return true statement was placed. I even went on to explain why placing the return statement where you had it would return different results from the freecodecamp solution. I think @PortableStick put it best, this is


#18

That’s not a lie, that’s a mistake. Please learn to handle interpersonal problems more appropriately.

Since your question has been answered and we’ve established what should not be said, I’m going to close this thread.


#19