简体   繁体   中英

Append items of array or exclude if already exists

as I describe my problem in title, I need implement following algorithm:

I got some array of elements, eg:

let arr1 = [
  {id:1, foo1: '...', foo2: '...'}, 
  {id:2, foo1: '...', foo2: '...'}, 
  {id:3, foo1: '...', foo2: '...'}, 
];

in somewhere in my application I got another array arr2 which can contains elements which already are in arr1.

let arr2 = [
  {id:1, foo1: '...', foo2: '...'}, 
  {id:4, foo1: '...', foo2: '...'}, 
  {id:5, foo1: '...', foo2: '...'}, 
];

In case arr1 contains each element of arr2 I need exclude these elements from arr1. And in second case where arr2 contains least one element which is also not in arr1, all elements of arr2 will append to arr1.

I tried lodash's function _.xorBy(arr1, arr2, 'id') which doesn't work in all cases. I looked for in lodash's docs some another function for my needs but I didn't found anything.

Here is my expected behavior (I use just number but in real app there objects with this ids):

  • given: arr1=[1,2,3,4,5] and arr2=[1,2,3] => resultArr=[4,5]
  • given: arr1=[1,2,3,4,5] and arr2=[1,2,6] => resultArr=[1,2,3,4,5,6] //6 is different so append all

Can you help me solve my problem, or show my some elegant way to do that? Thanks in advice.

If the _.difference() array length between arr2 and arr1 is greater than 0 , return a _.union() of the arrays. If not return the _.difference() between arr1 and arr2 .

Note 1: _.difference(arr2, arr1) is not equal to _.difference(arr1, arr2) because the order and references of result values are determined by the first array.

Note 2: The example uses arrays of primitives. For arrays of objects use the By versions - _.differenceBy() and _.unionBy() with the property iteratee shorthand - _.differenceBy(arr1, arr2, 'id') .

 const incEx = (arr1, arr2) => _.difference(arr2, arr1).length > 0 ? _.union(arr1, arr2) : _.difference(arr1, arr2); console.log(incEx([1,2,3,4,5], [1,2,3])); console.log(incEx([1,2,3,4,5], [1,2,6])); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script> 

A plain Javascript solution with Set .

 function merge(array1, array2) { var ids1 = new Set(array1.map(({ id }) => id)), ids2 = new Set(array2.map(({ id }) => id)); return array2.every(({ id }) => ids1.has(id)) ? array1.filter(({ id }) => !ids2.has(id)) : array1.concat(array2.filter(({ id }) => !ids1.has(id))); } var array1 = [{ id: 1 }, { id: 2 }, { id: 3 }], array2 = [{ id: 1 }, { id: 4 }, { id: 5 }]; console.log(merge(array1, array2)); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

In case arr1 contains each element of arr2 I need exclude these elements from arr1.

To check if all arr2 is contained in arr1

var hasAllValues = arr2.every( s => !!arr1.find( t => t.id == s.id ) )

hasAllValues is true if all arr2 is in contained in arr1

Use filter to remove those values in arr1 ,

arr1 =  arr1.filter( s => arr2.find( t => t.id == s.id ) );

And in second case where arr2 contains least one element which is also not in arr1, all elements of arr2 will append to arr1.

find the values of arr2 which are not arr1 using

var arr3 =  arr2.filter( s => !!arr1.find( t => t.id == s.id ) );
arr1 = arr1.concat( arr3 );

So, final solution would be

var hasAllValues = arr2.every( s => !!arr1.find( t => t.id == s.id ) )
if ( hasAllValues )
{
   arr1 =  arr1.filter( s => !arr2.find( t => t.id == s.id ) );
}
else
{
   var arr3 =  arr2.filter( s => !arr1.find( t => t.id == s.id ) );
   arr1 = arr1.concat( arr3 );
}

Demo of scenario 1

 let arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]; let arr2 = [{ id: 1 }, { id: 4 } ]; var hasAllValues = arr2.every(s => !!arr1.find(t => t.id == s.id)) if (hasAllValues) { arr1 = arr1.filter(s => !arr2.find(t => t.id == s.id)); } else { var arr3 = arr2.filter(s => !arr1.find(t => t.id == s.id)); //console.log(arr3) arr1 = arr1.concat(arr3); } console.log(arr1); 

Demo of scenario 2

 let arr1 = [{ id: 1 }, { id: 2 }, { id: 3 } ]; let arr2 = [{ id: 1 }, { id: 4 }, { id: 5 } ]; var hasAllValues = arr2.every(s => !!arr1.find(t => t.id == s.id)) if (hasAllValues) { arr1 = arr1.filter(s => !arr2.find(t => t.id == s.id)); } else { var arr3 = arr2.filter(s => !arr1.find(t => t.id == s.id)); //console.log(arr3) arr1 = arr1.concat(arr3); } console.log(arr1); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM