Najam Us Saqib
Najam Us Saqib

Reputation: 3404

Remove same Values from array of Object

I want to remove same object from array by comparing 2 arrays.

Sample Data:

arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
];

arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

let newArray = []; // new array with with no same values it should be unique.
arr1.map((val, i)=>{
   arr2.map((val2)=>{
    if(val.id == val2.id){
       console.log('Matched At: '+ i) // do nothing
    }else{
      newArray.push(val);
    }
   })
})
console.log(newArray); // e.g: [{id: 2, name: "b"}, {id: 3, name: "c"},];

Upvotes: 5

Views: 869

Answers (8)

Keith
Keith

Reputation: 24181

Array.filter combined with not Array.some.

The trick here is also to not some,..

const arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
], arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

const newArray=arr1.filter(a=>!arr2.some(s=>s.id===a.id));

console.log(newArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

As mentioned in comments the question could be interpreted slightly differently. If you also want the unqiue items from arr2, you basically just do it twice and join. IOW: check what not in arr2 is in arr1, and then check what not in arr1 that's in arr2.

eg..

const notIn=(a,b)=>a.filter(f=>!b.some(s=>f.id===s.id));
const newArray=[...notIn(arr1, arr2), ...notIn(arr2, arr1)];

Update 2: Time complexity, as mentioned by qiAlex there is loops within loops. Although some will short circuit on finding a match, if the dataset gets large things could slow down. This is were Set and Map comes in.

So to fix this using a Set.

const notIn=(a,b)=>a.filter(a=>!b.has(a.id));
const newArray=[
  ...notIn(arr1, new Set(arr2.map(m=>m.id))),
  ...notIn(arr2, new Set(arr1.map(m=>m.id)))
];

Upvotes: 7

qiAlex
qiAlex

Reputation: 4346

So many loops in every answer.

Complexity of the code my answer is 2N,

Idea is:

  1. to merge arrays.

  2. first loop - mark duplicates somehow

  3. second loop - filter duplicates out

arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
];

arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

let newArray = [...arr1, ...arr2].reduce((acc, item, index) => {
  acc.items.push(item);

  if (typeof acc.map[item.id] !== 'undefined') {
    acc.items[acc.map[item.id]] = null;
    acc.items[index] = null;
  }
  acc.map[item.id] = index;
  
  return acc
},  {map: {}, items: []}).items.filter(item => !!item)


console.log(newArray);

Upvotes: 1

Ankit Kumar Rajpoot
Ankit Kumar Rajpoot

Reputation: 5590

Try this one -

const arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
];

const arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

const arr3 = [...arr1, ...arr2];
const mySubArray = _.uniq(arr3, 'id');
console.log(mySubArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Upvotes: 1

StepUp
StepUp

Reputation: 38094

We can filter values by checking whether some element is not contained in current array:

const result = arr1.reduce((a, c) => {
  if (!arr2.some(a2 => a2.id === c.id))
      a.push(c);
  return a;
}, [])

An example:

let arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
];

let arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

const result = arr1.reduce((a, c) => {
  if (!arr2.some(a2 => a2.id === c.id))
      a.push(c);
  return a;
}, [])

console.log(result);

Upvotes: 1

AbdurrahmanY
AbdurrahmanY

Reputation: 883

I think a simple comparer can works for getting differences and then concat them. with this method you dont need to check which array is bigger.

arr1 = [  {id: 1, name: "a"},  {id: 2, name: "b"},  {id: 3, name: "c"},  {id: 4, name: "d"}];

arr2 = [  {id: 1, name: "a"},  {id: 4, name: "d"},];

function localComparer(b){
  return function(a){
    return b.filter(
    function(item){
      return item.id == a.id && item.name == a.name
    }).length == 0;
  }
}

var onlyInArr1 = arr1.filter(localComparer(arr2));
var onlyInArr2 = arr2.filter(localComparer(arr1));

console.log(onlyInArr1.concat(onlyInArr2));

Upvotes: 1

Kunal Mukherjee
Kunal Mukherjee

Reputation: 5853

You check each element in first array whether its id lies in the second array by using Array.prototype.some. If the element is not present then only yield it.

const arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
];

const arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

const result = arr1.filter(x => !arr2.some(y => y.id === x.id));

console.log(result);

Upvotes: 1

Rob Brander
Rob Brander

Reputation: 3771

const isInArray = (arr, id, name) => arr.reduce((result, curr) => ((curr.name === name && curr.id === id) || result), false)

const newArray = arr1.reduce((result, curr) => (isInArray(arr2, curr.id, curr.name) ? result : result.concat(curr)), [])

Upvotes: 2

palaѕн
palaѕн

Reputation: 73896

You can update you code using filter() method, instead of using .map() method like:

const arr1 = [
  {id: 1, name: "a"},
  {id: 2, name: "b"},
  {id: 3, name: "c"},
  {id: 4, name: "d"},
], arr2 = [
  {id: 1, name: "a"},
  {id: 4, name: "d"},
];

let newArray = []; // new array with with no same values it should be unique.
newArray = arr1.filter(function(a) {
    for(var i=0; i < arr2.length; i++){
      if(a.id == arr2[i].id) return false;
    }
    return true;
});
console.log(newArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions