Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge two arrays, avoiding duplicates using immutable pattern in redux

Let's say I have two arrays:

let A = [a,b,c,d]
let B = [c,d,e]

where each of the letters is an object that has several properties, one of which is an id which is unique in my domain. The merged result would then be

[a,b,c,d,e]

where [c,d] originate from B.

Using an elegant approach, how would I merge these two arrays in a way that any element in B would overwrite any existing one in A and all others remain untouched. So it's a union with B elements taking precedence in case of a conflict.

I have two ideas (using ES6 and lodash):

//remove same elements first, then join arrays
let ids = new Set(B.map(e => e.id));
let newState = _.reject(A, constraint => ids.has(constraint.id));
return newState.concat(B);

//convert both to hashmap, join, then take values
let B_map = _.keyBy(B, 'id');
let A_map = _.keyBy(A, 'id');
return {...A_map, ...B_map}.values();

Is there a shorter / more concise / more readable version? Maybe one without external dependencies? I'm essentially looking for something like

Where equality between any element is defined by the id property (or a comparator function in v2).

like image 638
pascalwhoop Avatar asked Mar 05 '23 21:03

pascalwhoop


1 Answers

Without external dependencies, you can use filter to extract elements from A that don't have ids in B and concat that with B:

const A = [{id: 1, name: 'x'}, {id: 2, name: 'y'}, {id: 3, name: 'z'}];
const B = [{id: 2, name: 'hello'}];

let ids = new Set(B.map(e => e.id));
let newState = A.filter(a => !ids.has(a.id)).concat(B);

console.log(newState);
like image 195
slider Avatar answered Apr 27 '23 17:04

slider