Reputation: 693
I'm having a bad time comparing two array of objects on a key.
I would like to compare, substract value when the key matches and display negative value when not in my target array. Finally, I want to have all target objects (if key didn't match) inside my final array.
An exemple would save 1000 words :
const initial = [{id: 1, value: 47}, {id: 2, value: 20}, {id: 7, value: 13}];
const target = [{id: 1, value: 150}, {id: 3, value: 70}, {id: 40, value: 477}];
//Desired output
// [{id: 1, value: 103}, {id: 2, value: -20}, {id: 7, value: -13}, {id: 3, value: 70}, {id: 40, value: 477}];
let comparator = [];
initial.map(initia => {
let hasSame = target.find(targ => {
return initia.id === targ.id
});
if(hasSame){
initia.value -= hasSame.value
} else{
initia.value = -initia.value
}
});
console.log(initial);
I'm getting almost the result I want except that I don't know how to merge target values properly. Is it possible to merge this values without looping over target array once more? Or could I do that inside the find
?
I want to get advice to do this as clean as possible
Thanks you!
Upvotes: 2
Views: 843
Reputation: 56
If the intent is to avoid a nested find inside of the loop, you could reduce the two arrays in to a Set. They don't allow duplicate keys, so you would ensure a single value for each ID provided.
const valueSet = [...initial, ...target].reduce((total, obj) => {
total[obj.id] = !total[obj.id]
? -obj.value
: total[obj.id] -= obj.value
return total;
}, {});
const result = Object.keys(valueSet).map(key => ({ id: key, value: valueSet[key]}))
console.log(result);
Then you'd map back over the result to build out the intended array.
Upvotes: 1
Reputation: 386600
You could use a Map
and collect same id
with a wanted factor for summing.
As result take key/value as new properties.
var add = (map, factor) => ({ id, value }) => map.set(id, map.has(id)
? map.get(id) - value * factor
: value * factor
),
initial = [ {id: 1, value: 47 }, { id: 2, value: 20 }, { id: 7, value: 13 }],
target = [{ id: 1, value: 150 }, { id: 3, value: 70 }, { id: 40, value: 477 }],
map = new Map,
result;
initial.forEach(add(map, -1));
target.forEach(add(map, 1));
result = Array.from(map, ([id, value]) => ({ id, value }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2