Reputation: 323
I am trying to merge data from json that comes in array of objects. I was using the underscore solution from here merge two json object based on key value in javascript, but it turns out it doesnt override existing items which I need to do as well now.
The result should be all items of array 1 in the same order, overriden by array 2 where id = id. Items in array 2 that does not exist in array 1 should be pushed to the end of the result.
First array:
[
{id: 8, category: "A"}
{id: 2, category: "D"}
{id: 5, category: "C"}
{id: 9, category: "B"}
]
Second array:
[
{id: 1, category: "X"}
{id: 2, category: "Y"}
]
Expected result:
[
{id: 8, category: "A"}
{id: 2, category: "Y"}
{id: 5, category: "C"}
{id: 9, category: "B"}
{id: 1, category: "X"}
]
Upvotes: 3
Views: 2718
Reputation: 25
This should work:
const newArr = second.reduce((res, item) => res.filter(i => i.id !== item.id).concat(item), first);
Upvotes: 0
Reputation: 323
Using underscore I managed to come up with this answer my own question. It is probably not the most efficent
const newarr = _.map(arr1, obj1 => {
const r = _.find(arr2, obj2 => {
return obj1[match] === obj2[match]
})
if (typeof r === 'undefined') {
return obj1
} else {
return r
}
})
_.each(arr2, obj => {
if (_.indexOf(arr1, _.findWhere(arr1, {id: obj.id})) === -1) {
newarr.push(obj)
}
})
Upvotes: 0
Reputation: 59
I think reduce is better
first.reduce((res, item) => res.filter(i => i.id !== item.id).concat(item), second);
Upvotes: 0
Reputation: 22544
You can use a forEach
to iterate through second
array. For each object with the same id in the first array, update the category
otherwise push in the new array.
const first = [{id: 8, category: "A"},{id: 2, category: "D"},{id: 5, category: "C"},{id: 9, category: "B"}],
second = [{id: 12, category: "X"},{id: 2, category: "Y"}],
merged = [...first];
second.forEach(o => {
let obj = first.find(({id,category}) => id === o.id);
obj ? obj.category = o.category : merged.push({...o});
});
console.log(merged);
Upvotes: 0
Reputation: 68393
Use filter
, find
and concat
Given that
var arr1 = [
{id: 8, category: "A"},
{id: 2, category: "D"},
{id: 5, category: "C"},
{id: 9, category: "B"}
];
var arr2 = [
{id: 12, category: "X"},
{id: 2, category: "Y"}
];
If the order is not important
var output = arr2.concat(
arr1.filter( s =>
!arr2.find( t => t.id == s.id )
)//end filter
);//end concat
Demo
var arr1 = [{
id: 8,
category: "A"
},
{
id: 2,
category: "D"
},
{
id: 5,
category: "C"
},
{
id: 9,
category: "B"
}
];
var arr2 = [{
id: 12,
category: "X"
},
{
id: 2,
category: "Y"
}
];
var output = arr2.concat(
arr1.filter(s =>
!arr2.find(t => t.id == s.id)
) //end filter
); //end concat
console.log(output);
If the order is important
var output = arr1.map(
s => arr2.find(
t => t.id == s.id ) || s
).concat( //end map of arr1
arr2.filter(
s => !arr1.find( t => t.id == s.id )
) //end filter
);//end concat
Demo
var arr1 = [{
id: 8,
category: "A"
},
{
id: 2,
category: "D"
},
{
id: 5,
category: "C"
},
{
id: 9,
category: "B"
}
];
var arr2 = [{
id: 12,
category: "X"
},
{
id: 2,
category: "Y"
}
];
var output = arr1.map(
s => arr2.find(
t => t.id == s.id) || s
).concat( //end map of arr1
arr2.filter(
s => !arr1.find(t => t.id == s.id)
) //end filter
); //end concat
console.log(output);
Upvotes: 9
Reputation: 30739
You can set a loop on your secondArray
and check each object with id
value against object with id
of firstArray
. If you find a match then simply replace the object else push the object:
var firstArray = [
{id: 8, category: "A"},
{id: 2, category: "D"},
{id: 5, category: "C"},
{id: 9, category: "B"}
];
var secondArray = [
{id: 12, category: "X"},
{id: 2, category: "Y"}
];
secondArray.forEach((obj)=>{
var match = false;
for(var i=0; i<firstArray.length; i++){
if(firstArray[i].id === obj.id){
match = true;
firstArray[i] = obj;
break;
}
}
if(!match){
firstArray.push(obj);
}
});
console.log(firstArray);
Upvotes: 0
Reputation: 386654
You could use a Map
as closure and store the index of the result array for this id
.
var first = [{ id: 8, category: "A" }, { id: 2, category: "D" }, { id: 5, category: "C" }, { id: 9, category: "B" }],
second = [{ id: 12, category: "X" }, { id: 2, category: "Y" }],
result = [first, second].reduce((m => (r, a) => {
a.forEach(o => {
if (m.has(o.id)) {
r[m.get(o.id)] = o;
return;
}
m.set(o.id, r.push(o) - 1);
});
return r;
})(new Map), []);
console.log(result);
Upvotes: 0