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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.