I have two arrays, which look like this:
const persons = [
{
id: 1,
name: 'Peter',
job: 'Programmer'
},
{
id: 2,
name: 'Jeff',
job: 'Architect'
},
];
const salaries = [
{
id: 1,
salary: 3000,
departments: ['A', 'B']
},
{
id: 1,
salary: 4000,
departments: ['A', 'C']
},
{
id: 2,
salary: 4000,
departments: ['C', 'D']
}
];
Now I need to somehow merge this arrays to one, so that every id only exists once. Same keys should be replaced, except it is an array, then I want them to add/concat. So the desired result should look something like this:
const result = [
{
id: 1,
name: 'Peter',
job: 'Programmer',
salary: 4000,
departments: ['A', 'B', 'C']
},
{
id: 2,
name: 'Jeff',
job: 'Architect',
salary: 4000,
departments: ['C', 'D']
}
];
I have already tried:
// double id's, arrays get replaced
Object.assign({}, persons, salaries)
// loadsh: double id's, arrays get concatenated
_.mergeWith(persons, salaries, (objValue, srcValue) => {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
});
// gives me a map but replaces arrays
new Map(salaries.map(x => [x.id, x])
Does anyone have an idea how to accomplish this?
You can concat the arrays, than combine all items with the same id
using Array.reduce()
, and a Map.
to combine objects with the same id
, get the object from the Map. Iterate the new Object.entries()
with Array.forEach()
. Check if existing value is an array, if not assign the value. If it is an array, combine the arrays, and make the items unique using a Set with array spread.
To convert the Map back to an array, you can spread the Map.values()
iterator.
const persons = [{"id":1,"name":"Peter","job":"Programmer"},{"id":2,"name":"Jeff","job":"Architect"}];
const salaries = [{"id":1,"salary":3000,"departments":["A","B"]},{"id":1,"salary":4000,"departments":["A","C"]},{"id":2,"salary":4000,"departments":["C","D"]}];
const result = [...persons.concat(salaries)
.reduce((r, o) => {
r.has(o.id) || r.set(o.id, {});
const item = r.get(o.id);
Object.entries(o).forEach(([k, v]) =>
item[k] = Array.isArray(item[k]) ?
[...new Set([...item[k], ...v])] : v
);
return r;
}, new Map()).values()];
console.log(result);