freeCodeCamp Algorithm Challenge Guide: Wherefore Art Thou

freeCodeCamp Algorithm Challenge Guide: Wherefore Art Thou
0.0 0

#1

:triangular_flag_on_post: Remember to use Read-Search-Ask if you get stuck. Try to pair program :busts_in_silhouette: and write your own code :pencil:

:checkered_flag: Problem Explanation:

Write an algorithm that will take an array for the first argument and return an array with all the objects that matches all the properties and values in the Object passed as second parameter.

Relevant Links

:speech_balloon: Hint: 1

You may use for loop or the Array.prototype.filter method.

try to solve the problem now

:speech_balloon: Hint: 2

Try to use the Object.prototype.hasOwnProperty method to know if the property name exists in an object (as its own property).

try to solve the problem now

:speech_balloon: Hint: 3

Check equivalence of Object in collection with Object passed as second parameter to whatIsInAName function.

try to solve the problem now

Spoiler Alert!

687474703a2f2f7777772e796f75726472756d2e636f6d2f796f75726472756d2f696d616765732f323030372f31302f31302f7265645f7761726e696e675f7369676e5f322e676966.gif

Solution ahead!

:beginner: Basic Code 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;
  });
}

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

:rocket: Run Code

Code Explanation:

  • We filter through the array using .filter().
  • Using a for loop we loop through each item in the object.
  • We use a if statement to check if the object in the collection doesn’t have the key and the property value doesn’t match the value in source.
  • We return false if the above if statement is correct. Otherwise, we return true;

Relevant Links

:sunflower: Intermediate Code 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);

  return collection.filter(function (obj) {
    return srcKeys.every(function (key) {
      return obj.hasOwnProperty(key) && obj[key] === source[key];
    });
  });
}

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

:rocket: Run Code

Code Explanation:

  • We filter through the collection using .filter().
  • Next, we return a Boolean value for the .filter() method.
  • Finally, we reduce to Boolean value to be returned for the .every() method.

Relevant Links

:rotating_light: Advanced Code 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) {
    return srcKeys
      .map(function(key) {
        return obj.hasOwnProperty(key) && obj[key] === source[key];
      })
      .reduce(function(a, b) {
        return a && b;
      });
  });
}

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

:rocket: Run Code

Code Explanation:

  • We start by filtering through collection using Array.filter().
  • Next, we map through all keys and return Boolean values based on the check conditions: both the key and its corresponding value must exist within the object we are filtering through.
  • Then we reduce the mapped Boolean values to a single Boolean that indicates whether all srcKeys pass the conditions checked above.
  • This single Boolean will be used to filter through the collection.

Relevant Links

:clipboard: NOTES FOR CONTRIBUTIONS:

  • :warning: DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
  • Add an explanation of your solution.
  • Categorize the solution in one of the following categories — Basic, Intermediate and Advanced. :traffic_light:
  • Please add your username only if you have added any relevant main contents. (:warning: DO NOT remove any existing usernames)

See :point_right: Wiki Challenge Solution Template for reference.


Question about reduce method - freeCodeCamp Algorithm Challenge Guide: Wherefore Art Thou
#2

There is a bug in the ‘advanced’ solution above. I made a PR to the old wiki project, but was told to contribute here instead. Would be great if the ‘advanced’ solution could be updated. Details can be found here: https://github.com/FreeCodeCamp/wiki/pull/1246


#4

@sautille is still a ‘new user’, once enough trust/reputation is built to progress to ‘basic user’ people can edit wiki posts.

From memory you just need to read a few posts and interact a little to ‘level up’.

Edit


#6

This is just a basic mechanism to avoid spaming.


#7

@sautille: I have updated the changes to match and reflect the pull request you made earlier and the change on the main repository as well.

Thanks for contributing.


#8

Great post i apprecialte your efforts!


#9

#10

#11

I’ve tried to solve this and gotten 2/4 green marks but gave up and came here to take a peek.

But I only got more confused. The exersize says to only change code between the lines.

 var arr = [];
  // Only change code below this line
  
  
  // Only change code above this line
  return arr;

But all the solutions posted here ignore that.


#12

I also got 2/4 green marks using the code below… I understand why my code doesn’t work but I was wondering if anyone knows if it’s possible to make this approach work (without using the filter() method) considering that the exercise tells us not to change the code between the lines. Cheers!

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  for (var i = 0; i < collection.length; i++) {
    for (var prop in source) {
      if (collection[i].hasOwnProperty(prop) && collection[i][prop] === source[prop]) {
        arr.push(collection[i]);
      }
    }
  }
  // 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 });

#13

@jacobworrel I think your code is pushing to arr when only ONE property is matched. However, sometimes the source has more than one, an all must be matched.


#14

Right.I just wonder if there’s any way to make my code work when there is more than one property…


#15

Help! Can anyone tell me why my code removed the "" from the keys in my solution?
Here’s my code:

function whatIsInAName(collection, source) {
	var arr=[];
	var k = Object.getOwnPropertyNames(source); 
	var v = source[k]; // assigns var to value in key value pair

	//loop through array of objects
	 for (var i = 0; i < collection.length; i++) {

		//check each object for matching key
	 	if (collection[i].hasOwnProperty(k)) {
	 		
			if (collection[i][k] == v ) { // if object has a match of key value pair...
				arr.push(collection[i]); // add object to arr
			}
		}
	 }
	return arr;
}

The code passed for the 1st test:

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

but the 2nd didnt pass (keys aren’t in double quotes).

2nd test:
whatIsInAName([{ "a": 1 }, { "a": 1 }, { "a": 1, "b": 2 }], { "a": 1 })

my function returned this:

[ { a: 1 }, { a: 1 }, { a: 1, b: 2 } ]

instead of this:
[{ "a": 1 }, { "a": 1 }, { "a": 1, "b": 2 }]

Why were my keys changed when I pushed them to arr?

And why do none of the spoiler solutions use the starter code that was there? (where the last line is return arr?)


#16

Is it the answer they were looking for? Probably not, given the replies, but I found a solution that works and just thought I would pass it on. Cheers!

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  
var name,
    key,
    soVal,
    coVal;
for(name in source){
  soVal = source[name];
} 
    var i=0;
      for(i; i< collection.length; i++) {
        var obj = collection[i];
          for(key in obj){
            coVal = obj[key];
            if (coVal == soVal && name == key) {
            arr.push(obj);
            }
          } 
      }
     
  // Only change code above this line
  return arr;
}

#17

FYI, the code above for the advanced solution is corrected, but the repl.it it links to still has the old code.


#18

do we have to use the methods in helpful links?

the filter() method works as well


#19

This solution worked for me and it shares your approach. It passed all the test cases.

function whatIsInAName(collection, source) {
  var arr = [];
for (var keyd in source){
 }for (var key in collection){
     if (source[keyd] === collection[key][keyd]){
          arr.push(collection[key]);}
}return(arr);}

#20

I solved this with a comparing the objects.
Here is the code:

function whatIsInAName(collection, source) {
  // What's in a name?  
  return collection
    .filter((obj) => JSON.stringify(Object.assign(JSON.parse(JSON.stringify(obj)), source)) === JSON.stringify(obj));
}

Does comparing the objects works faster or slower relatively to using the loop with comparing properties. (Sry for bad English :slight_smile: )


#21

I solved that with couple for loops, it is not elegant as some above solutions, but it works:

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  
  arr = Array.prototype.slice.call(arguments);
  // Only change code below this line
  
  
  var key = Object.keys(source);
  var returncollection =[];
 
  for (i=0; i<collection.length; i++)
    {     
   for (j=0; j<key.length; j++)
    {
     if (collection[i].length<key.length)
       {
        break; 
       } 
     if (collection[i][key[j]]!==source[key[j]])
       {
        break; 
       }
      if (j==key.length-1)
       {
        returncollection = returncollection.concat(collection[i]);
       }
     }      
    }
    //collection2 = collection2.concat(collection[i]);     
  
  // Only change code above this line Object.keys(collection[i])[j]
  return returncollection;
}

#22

Some really interesting solutions in here.

Here is my solution that turned out pretty close to the basic spoiler. I even ended up using some same variable names by coincidence.

I couldn’t figure out an elegant solution in the if/else statement like the basic solution spoiler does on this line:
if(!obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i]] !== source[srcKeys[i]])
but I figured out an interesting way to get my return to be true if the tests were passed.

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

  arr = collection.filter(function(obj) {
    var srcKeys = Object.keys(source); 
    var test = 0;
    for (var i = 0; i < srcKeys.length; i++) {
      if (obj.hasOwnProperty(srcKeys[i]) && obj[srcKeys[i]] === source[srcKeys[i]]) {
        test += 1;
      } else {
        test += -1;
      }
    }
    return test === srcKeys.length;
  });
  
  // Only change code above this line
  return arr;
}

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