1

I have an array of objects that I'd like to filter to create a new array based on whether or not the value of any key matches any value in another array.

const array1 = [{name: 'pink', id: 13}, {name: 'orange', id: 17}, {name: 'red, id: 64}, {name: 'purple', id: 47}, {name: 'yellow', id: 23}, {name: 'gray', id: 2}, {name: 'black', id: 200}, {name: 'violet', id: 4}]

const array2 = ['red', 'blue', 'green', 'pink']

I've tried using a for...of loop inside of a return function but that is giving me errors.

    const array3 = array1.filter(color => {
        for (mainColor of array2){
            return color.name === mainColor 
        }
    });

This works but is clearly not the best way.

    const array3 = array1.filter(color => {
            return (color.main === 'red') || (color.main === 'blue')
        });

How can I get a third array from array1 that contains only the objects where the array1.name matches a value in array2?

Is it possible with ES6 or Lodash?

Thanks in advance!

3
  • That's a for...in loop you're using, not a for...of. Commented Mar 6, 2018 at 15:12
  • oops you're right, updated! still doesn't work though. Commented Mar 6, 2018 at 15:17
  • It does not work, because you are using return inside the loop, thus iterating only over the first element before exiting. If you want to use a for loop, you have to check whether the condition is true and return true only then. Commented Mar 6, 2018 at 15:19

5 Answers 5

4

Almost there, instead of for-loop use includes and return

const array3 = array1.filter(color => {
    return array2.includes ( color.name );
});

Or

const array3 = array1.filter( color => array2.includes ( color.name ) );
Sign up to request clarification or add additional context in comments.

Comments

3

Let me give an alternative, that has slightly more code, but is more efficient as well, as it only needs to scan array2 once:

const array1 = [{name: 'pink', id: 13}, {name: 'orange', id: 17}, {name: 'red', id: 64}, {name: 'purple', id: 47}, {name: 'yellow', id: 23}, {name: 'gray', id: 2}, {name: 'black', id: 200}, {name: 'violet', id: 4}],
      array2 = ['red', 'blue', 'green', 'pink'];

const colorSet = new Set(array2),
      array3 = array1.filter(color => colorSet.has(color.name));

console.log(array3);

2 Comments

Do you think is worth it a previous process with new Set(...) just to check if a color exists in array2? Just to remove the repeated? or Set has a better algorithm?
The has method works in constant time, while includes or indexOf need linear time, so when that is in a loop, you get O(n²) time complexity, while with a set you'll just have O(n) both for the new Set and the loop, and O(n)+O(n) is still O(n). Of course, all this is not very relevant when we speak of an array that has a limited number of entries, not hundreds of them.
1

Try the following with Array's includes():

const array1 = [{name: 'pink', id: 13}, {name: 'orange', id: 17}, {name: 'red', id: 64}, {name: 'purple', id: 47}, {name: 'yellow', id: 23}, {name: 'gray', id: 2}, {name: 'black', id: 200}, {name: 'violet', id: 4}]

const array2 = ['red', 'blue', 'green', 'pink'];

const array3 = array1.filter(color => array2.includes(color.name));

console.log(array3);

Comments

0

The filter method already iterates on each item. You just have to return true if the element is present in the second array (by using indexOf or includes)

const array1 = [{name: 'pink', id: 13}, {name: 'orange', id: 17}, {name: 'red', id: 64}, {name: 'purple', id: 47}, {name: 'yellow', id: 23}, {name: 'gray', id: 2}, {name: 'black', id: 200}, {name: 'violet', id: 4}]

const array2 = ['red', 'blue', 'green', 'pink'];

let filteredArray = array1.filter(e => array2.indexOf(e.name) > -1);

console.log(filteredArray);

Comments

0

I know indexOf might seem a little outfashioned and ES5-ish, but it still does the job:

const array1 = [{name: 'pink', id: 13}, {name: 'orange', id: 17}, {name: 'red', id: 64}, {name: 'purple', id: 47}, {name: 'yellow', id: 23}, {name: 'gray', id: 2}, {name: 'black', id: 200}, {name: 'violet', id: 4}],
  array2 = ['red', 'blue', 'green', 'pink'];

let array3 = array1.filter(x => array2.indexOf(x.name) != -1)
console.log(array3)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.