sfasfasd
sfasfasd

Reputation: 97

Filter out an array from the duplicates in another array

Given these two arrays:

const array1 = [
                {"id": 1, "color": "black"},
                {"id": 2, "color": "white"},
                {"id": 3, "color": "orange"}
               ];

const array2 = [
                {"id": 2, "color": "white"},
                {"id": 4, "color": "purple"}
               ];

How could I remove the duplicates from the first array if found in the second, i.e. the result would be:

const filtered = [
                  {"id": 1, "color": "black"},
                  {"id": 3, "color": "orange"}
                 ];

My code:

const filtered = array1.map(i => array2.filter(j => i["id"] !== j["id"]))

but it doesn't seem to work

Upvotes: 2

Views: 1361

Answers (4)

Code Maniac
Code Maniac

Reputation: 37757

To make your code work you can use filter and every

const array1 = [ {"id": 1, "color": "black"},{"id": 2, "color": "white"},{"id": 3, "color": "orange"}];
const array2 = [{"id": 2, "color": "white"},{"id": 4, "color": "purple"}];

const filtered = array1.filter(i => array2.every(j => i["id"] !== j["id"]))

console.log(filtered)

You can use Map and filter

const array1 = [ {"id": 1, "color": "black"},{"id": 2, "color": "white"},{"id": 3, "color": "orange"}];
const array2 = [{"id": 2, "color": "white"},{"id": 4, "color": "purple"}];

let mapper = new Map(array2.map(v=> [v.id,v]))

const final = array1.filter(({id})=> !mapper.has(id))

console.log(final)

Upvotes: 3

Naina Dhawani
Naina Dhawani

Reputation: 1

If you want to filter array based on any key-value match is found in second array, a solution using forEach and every:

function filterArray(arr1, arr2) {
    let filterArr = [];
    arr1.forEach(item => 
       arr2.every( val => val.id !== item.id && val.color !== item.color) && filterArr.push(item));

    return filterArr;
}

Upvotes: 0

Fullstack Guy
Fullstack Guy

Reputation: 16908

We can use Array.prototype.filter to filter the first array. The filter condition can be constructed by various means having different time complexities:

  1. Linear time by using the Array.prototype.findIndex which will check if the current object is included in the second array:

const array1 = [{"id": 1, "color": "black"}, {"id": 2, "color": "white"}, {"id": 3, "color": "orange"}];
const array2 = [{"id": 2, "color": "white"}, {"id": 4, "color": "purple"}];

function filterArray(array1, array2,){
  return array1.filter( ({id}) => array2.findIndex((o) => id === o.id ) < 0);
}
console.log(filterArray(array1, array2));

  1. Or this can also be done efficiently by using a Set which has a constant time lookup:

const array1 = [{"id": 1, "color": "black"}, {"id": 2, "color": "white"}, {"id": 3, "color": "orange"}];
const array2 = [{"id": 2, "color": "white"}, {"id": 4, "color": "purple"}];

function filterArrayUsingSet(array1, array2){
  const lookup = new Set(array2.map(({id})  => id));
  return array1.filter( ({id}) => !lookup.has(id) );
}

console.log(filterArrayUsingSet(array1, array2));

  1. Even a Object literal can be used as a key lookup table, where the key will be the ids of array2 this will also be constant time lookup:

const array1 = [{"id": 1, "color": "black"}, {"id": 2, "color": "white"}, {"id": 3, "color": "orange"}];
const array2 = [{"id": 2, "color": "white"}, {"id": 4, "color": "purple"}];

function filterArrayUsingSet(array1, array2){
  const lookup = array2.reduce((acc, {id}) => {acc[id] = id; return acc}, {});
  return array1.filter( ({id}) => !(id in lookup));
}

console.log(filterArrayUsingSet(array1, array2));

Upvotes: 0

Vandesh
Vandesh

Reputation: 6894

If you want duplicates removed based on only 'id', you can do so using Array.filter() and Array.find() or Array.some() -

const filtered = array1.filter(x => !array2.find( y => y.id===x.id));

OR

const filtered = array1.filter(x => !array2.some( y => y.id===x.id));

Check this JS Bin to play around.

Upvotes: 0

Related Questions