# Wherefore Art Thou

## Problem Explanation

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

## Hints

### Hint 1

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

### Hint 2

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

### Hint 3

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

## Solutions

Solution 1 (Click to Show/Hide)
``````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" }
);
``````

#### 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`;

Solution 2 (Click to Show/Hide)
``````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" }
);
``````

#### 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.

Solution 3 (Click to Show/Hide)
``````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" }
);
``````

#### 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.

50 Likes

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

7 Likes

@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

4 Likes

This is just a basic mechanism to avoid spaming.

1 Like

@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.

5 Likes

Great post i apprecialte your efforts!

1 Like

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.

26 Likes

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 });``````
2 Likes

@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.

2 Likes

Right.I just wonder if thereâs any way to make my code work when there is more than one propertyâŚ

1 Like

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 } ]`

`[{ "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`?)

3 Likes

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;
}``````
9 Likes

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

the filter() method works as well

48 Likes

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);}``````
5 Likes

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 )

8 Likes

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;
}``````
6 Likes

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" });
``````
4 Likes