I have two arrays:
var odd = [
{ name : "1", extraProp1 : "propValue1" },
{ name : "3", extraProp1 : "propValue2"
The most efficient way I can see (although maybe not leveraging JS predefined functions) is making up a dictionary with the name
values as the keys.
You can go through the first array and populate the dictionary. Then you can iterate through the second array and add each element to the dictionary if it doesn't contain the name
or merge the objects if it does.
Example:
var odd = [
{ name : "1", extraProp1 : "propValue1" },
{ name : "3", extraProp1 : "propValue2"}
];
var even = [
{ name : "1", extraProp2 : "prop1" },
{ name : "2", extraProp2 : "prop2"},
{ name : "4", extraProp2 : "prop3" }
];
var combinedDictionary = {}
for(let obj of odd) {
combinedDictionary[obj.name] = obj;
}
for(let obj of even) {
combinedDictionary[obj.name] = {
...(combinedDictionary[obj.name] || {}),
...obj
};
}
var result = Object.keys(combinedDictionary).map(key => combinedDictionary[key]);
console.log(result);
Indeed, in your attempt you are correctly filtering a
, but you have no code that merges two objects.
I would also use a Map
for faster lookup than with a nested call of filter
:
function merge(a, b, prop) {
let map = new Map(b.map(o => [o[prop], o]));
return a.reduce((acc, o) => {
let match = map.get(o[prop]);
return match ? acc.concat({ ...o, ...match }) : acc;
}, []);
}
var odd = [
{ name : "1", extraProp1 : "propValue1" },
{ name : "3", extraProp1 : "propValue2"}
];
var even = [
{ name : "1", extraProp2 : "prop1" },
{ name : "2", extraProp2 : "prop2"},
{ name : "4", extraProp2 : "prop3" }
];
console.log(merge(odd, even, "name"));
The { ...o, ...match }
part performs the actual merge of two objects that was missing in your solution.