I want to update (replace) the objects in my array with the objects in another array. Each object has the same structure. e.g.
var origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
var updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
// desired result:
NEWArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
I've tried concat() & Underscore's _.uniq
function, but it always dumps the newer object & returns, essentially, the original array.
Is there a way to overwrite (replace) origArr
with the objects in updatingArr
-- matching on the name
property?
The concat() method concatenates (joins) two or more arrays. The concat() method returns a new array, containing the joined arrays. The concat() method does not change the existing arrays.
To merge duplicate objects in array of objects with JavaScript, we can use the array map method. to merge the items with the label value together. To do this, we get an array of labels without the duplicates with [... new Set(data.
To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ... ) Use the Object. assign() method.
I came here looking for exactly this, saw @Gruff Bunny 's technique and wondered if 'lodash' wouldn't perhaps be a superior option even to 'underscore'?
Lo and behold :
let result = _.unionBy(updatingArr, origArr, 'name');
Using a double for loop and splice you can do it like so:
for(var i = 0, l = origArr.length; i < l; i++) {
for(var j = 0, ll = updatingArr.length; j < ll; j++) {
if(origArr[i].name === updatingArr[j].name) {
origArr.splice(i, 1, updatingArr[j]);
break;
}
}
}
Example here
You could use Array#map
in combination with Array#reduce
var origArr = [{ name: 'Trump', isRunning: true }, { name: 'Cruz', isRunning: true }, { name: 'Kasich', isRunning: true }],
updatingArr = [{ name: 'Cruz', isRunning: false }, { name: 'Kasich', isRunning: false }],
NEWArr = origArr.map(function (a) {
return this[a.name] || a;
}, updatingArr.reduce(function (r, a) {
r[a.name] = a;
return r;
}, Object.create(null)));
document.write('<pre>' + JSON.stringify(NEWArr, 0, 4) + '</pre>');
UPDATE 2022
Using an object with name
as hash and mapping the original array by taking the update from hash table or the original object.
const
origArr = [{ name: 'Trump', isRunning: true }, { name: 'Cruz', isRunning: true }, { name: 'Kasich', isRunning: true }],
updatingArr = [{ name: 'Cruz', isRunning: false }, { name: 'Kasich', isRunning: false }],
updates = Object.fromEntries(updatingArr.map(o => [o.name, o])),
result = origArr.map(o => updates[o.name] || o);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another approach by using Map
.
This approach works for objects who are only in the updating array as well.
const
origArr = [{ name: 'Trump', isRunning: true }, { name: 'Cruz', isRunning: true }, { name: 'Kasich', isRunning: true }],
updatingArr = [{ name: 'Cruz', isRunning: false }, { name: 'Kasich', isRunning: false }],
result = Array.from([...origArr, ...updatingArr]
.reduce((m, o) => m.set(o.name, o), new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
const updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
let hash = {};
for(let i of origArr.concat(updatingArr)) {
if(!hash[i]) {
hash[i.name] = i;
}
}
let newArr = [];
for(let i in hash) {
newArr.push(hash[i])
}
console.log(newArr);
You can use a hash which gives the index by name, and Object.assign
to update.
var hash = origArr.reduce(function(hash, obj, index) {
hash[obj.name] = index;
return hash;
}, Object.create(null));
for(var obj of updatingArr) {
Object.assign(origArr[hash[obj.name]], obj);
}
You can give this a try.
var origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
var updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
var origLength = origArr.length;
var updatingLength = updatingArr.length;
//Traverse the original array and replace only if the second array also has the same value
for(i = origLength-1; i >= 0; i--) {
for(j = updatingLength -1; j >= 0; j--) {
if(origArr[i].name === updatingArr[j].name) {
origArr[i] = updatingArr[j];
}
}
}
console.log(origArr);
Here's a solution using underscore:
var result = _.map(origArr, function(orig){
return _.extend(orig, _.findWhere(updatingArr, {name: orig.name}));
});
This version lets you define the selector
that defines an object as duplicate.
>= 0
if two selectors are equal. If none are equal, it returns -1
const origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
const updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
const mergeArrayOfObjects = (original, newdata, selector = 'key') => {
newdata.forEach(dat => {
const foundIndex = original.findIndex(ori => ori[selector] == dat[selector]);
if (foundIndex >= 0) original.splice(foundIndex, 1, dat);
else original.push(dat);
});
return original;
};
const result = mergeArrayOfObjects(origArr, updatingArr, "name")
console.log('RESULT -->', result)
This will do what you need:
var origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
var updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
for (var i = 0; i < updatingArr.length; ++i) {
var updateItem = updatingArr[i];
for (var j = 0; j < origArr.length; ++j) {
var origItem = origArr[j];
if (origItem.name == updateItem.name) {
origItem.isRunning = updateItem.isRunning;
break;
}
}
}
document.write('<pre>' + JSON.stringify(origArr, 0, 4) + '</pre>');
Same as @gevorg answer, but you may want to also add a new object to the original array if no matches are found.
let combinedEvents = origEvents;
for(let i =0; i< newEvents.length; i++){
let newEvent = newEvents[i];
for(let j =0; j< origEvents.length; j++){
let origEvent = origEvents[j];
if(newEvent.events_id == origEvent.events_id){
combinedEvents.splice(j,1, newEvent);
break;
} else if(j === origEvents.length - 1){
combinedEvents.push(newEvent);
break;
}
}
}
In ES6 you can use the object Map like this...
let map = new Map();
let origArr = [
{name: 'Trump', isRunning: true},
{name: 'Cruz', isRunning: true},
{name: 'Kasich', isRunning: true}
];
let updatingArr = [
{name: 'Cruz', isRunning: false},
{name: 'Kasich', isRunning: false}
];
// Concating arrays with duplicates
let NEWArr = origArr.concat(updatingArr);
// Removing duplicates items
NEWArr.forEach(item => {
if(!map.has(item.name)){
map.set(item.name, item);
}
});
Array.from(map.values());
Remember: the Map object need in unique key, in this case I used the name
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With