If you want to merge 2 arrays of objects in JavaScript. You can use this one line trick
Array.prototype.push.apply(arr1,arr2);
For Example
var arr1 = [{name: "lang", value: "English"},{name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1); // final merged result will be in arr1
Output:
[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]
Answer from Jahanzaib Aslam on Stack OverflowIf you want to merge 2 arrays of objects in JavaScript. You can use this one line trick
Array.prototype.push.apply(arr1,arr2);
For Example
var arr1 = [{name: "lang", value: "English"},{name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1); // final merged result will be in arr1
Output:
[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]
With ES6 you can do it very easy as below:
var arr1 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var arr3 = [...arr1, ...arr2];
Output:
arr3 = [
{"name":"lang","value":"German"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}
]
A short review;
- This code looks incredibly complicated for what you want to achieve, sometimes a few
forloops beat the functional approach arrayis a global variable (notvarorsetorconst), that is a bad thing- If a function is not inline, I would encourage you to use the
functionkeyword - I am not sure
mergeLinesis a great name, perhapsmergeIds?
array = [{
id: 1,
items: [1, 2, 3]
},
{
id: 2,
items: [1, 2]
},
{
id: 1,
items: [4]
},
{
id: 3,
items: [1]
},
];
function mergeIds(list){
const out = [];
for(entry of list){
const existingEntry = out.find(o => o.id === entry.id);
if(existingEntry){
existingEntry.items = existingEntry.items.concat(entry.items);
} else {
out.push(entry);
}
}
return out;
}
console.log(mergeIds(array));
You can reduce the computational complexity to O(n) by putting the intermediate arrays into an object indexed by id. This way, for every array item, you just need to look up the id property on the object, and don't need to search through every item in the array for a possible match:
array = [{
id: 1,
items: [1, 2, 3]
},
{
id: 2,
items: [1, 2]
},
{
id: 1,
items: [4]
},
{
id: 3,
items: [1]
},
];
const mergeIds = (list) => {
const subarrsById = {};
for (const { id, items } of list) {
if (!subarrsById[id]) {
subarrsById[id] = { id, items: [...items] };
} else {
subarrsById[id].items.push(...items);
}
}
return Object.values(subarrsById);
}
console.log(mergeIds(array));
One caveat - this will result in the output array being sorted by ascending array index, rather than by order of occurrence in the original array (because that's how object keys are arranged). If that's an issue, you can use a Map instead.
array = [{
id: 1,
items: [1, 2, 3]
},
{
id: 2,
items: [1, 2]
},
{
id: 1,
items: [4]
},
{
id: 3,
items: [1]
},
];
const mergeIds = (list) => {
const subarrsById = new Map();
for (const { id, items } of list) {
if (!subarrsById.has(id)) {
subarrsById.set(id, { id, items: [...items] });
} else {
subarrsById.get(id).items.push(...items);
}
}
return [...subarrsById.values()];
}
console.log(mergeIds(array));
A suggestion regarding your original code:
processedIds.indexOf(elementId) === -1
When you want to check if an array contains an element, it's more natural to use .includes rather than an .indexOf check against -1.
Also, when creating a collection of processed primitives (like the IDs here), and you need to regularly check that collection to see if a particular primitive has been processed yet, consider using a Set and Set#has (O(1)) instead of an array and Array#includes (O(n)).
javascript - Merge arrays from object property in an object array - Stack Overflow
javascript - Merge Array of Objects by Property using Lodash - Stack Overflow
javascript - Merge objects in array based on property - Stack Overflow
Merge Array of objects that have the same properties
You can use Array.prototype.flatMap()
Code example 1:
const objArray = [{key: 'key1', fields: [1, 2]}, {key: 'key2', fields: [3, 4]}]
const result = objArray.flatMap(({ fields }) => fields)
console.log(result)
Also you can use Array.prototype.map() and Array.prototype.flat()
Code example 2:
const objArray = [{key: 'key1', fields: [1, 2]}, {key: 'key2', fields: [3, 4]}]
const result = objArray.map(({ fields }) => fields).flat()
console.log(result)
Also you can use Array.prototye.reduce() combined with destructuring assignment and spread syntax
Code example 3:
const objArray = [{key: 'key1', fields: [1, 2]}, {key: 'key2', fields: [3, 4]}]
const result = objArray.reduce((a, { fields }) => [...a, ...fields], [])
console.log(result)
Also using just Array.prototye.reduce() combined with Array.prototype.concat():
Code example 4:
const objArray = [{key: 'key1', fields: [1, 2]}, {key: 'key2', fields: [3, 4]}]
const result = objArray.reduce((a, { fields }) => a.concat(fields), [])
console.log(result)
You can simply concat the array and create a new array inside a loop:
var objArray = [{'key': 'key1', 'fields': [1, 2]}, {'key': 'key2', 'fields': [3, 4]}];
var result = [];
for(var i=0; i<objArray.length; i++){
result = result.concat(objArray[i].fields);
}
console.log(result);
_.unionBy():
This method is like _.union except that it accepts iteratee which is invoked for each element of each arrays to generate the criterion by which uniqueness is computed. Result values are chosen from the first array in which the value occurs.
var original = [
{ label: 'private', value: 'private@johndoe.com' },
{ label: 'work', value: 'work@johndoe.com' }
];
var update = [
{ label: 'private', value: 'me@johndoe.com' },
{ label: 'school', value: 'schol@johndoe.com' }
];
var result = _.unionBy(update, original, "label");
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Convert the lists to objects keyed by label, merge them by _.assign, and convert it back to an array. It will even retain order of the items on most browsers.
var original = [
{
label: 'private',
value: 'private@johndoe.com'
},
{
label: 'work',
value: 'work@johndoe.com'
}
];
var update = [
{
label: 'private',
value: 'me@johndoe.com'
},
{
label: 'school',
value: 'schol@johndoe.com'
}
];
console.log(
_.map(
_.assign(
_.mapKeys(original, v => v.label),
_.mapKeys(update, v => v.label)
)
)
);
// or remove more duplicated code using spread
console.log(
_.map(
_.assign(
...[original, update].map(
coll => _.mapKeys(coll, v => v.label)
)
)
)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Using reduce:
var merged = array.reduce(function(list, obj) {
var found = false;
for (var i = 0; i < list.length; i++) {
if (list[i].name == obj.name) {
list[i].myList = list[i].myList.concat(obj.myList);
found = true;
break;
}
}
if (!found) {
list.push(obj);
}
return list;
}, []);
Firstly you could remove the duplicate entries and organize the objects inside the myList array. Then, return an array of objects with specified keys, based on the ordered object from the first step.
var array = [{name:"One",myList:['Object1','Object2']},{name:"Two",myList:['Object3','Object4']},{name:"One",myList:['Object5','Object6']}], obj = {};
array.forEach(function(v) {
obj[v.name] = (obj[v.name] || []).concat(v.myList)
});
var arr = Object.keys(obj).reduce(function(s,a) {
s.push({name: a, myList: obj[a]});
return s;
}, []);
console.log(arr);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
I'm trying to merge multiple objects in an array into one object if they share the same ID. For instance...
var Students = [
{
ID : 1,
Name : "John Doe",
SponserID : 421,
SponserName : "Mark"
},
{
ID : 1,
Name : "John Doe",
SponserID : 341,
SponserName : "James"
},
{
ID : 2,
Name : "James Law",
SponserID : 421,
SponserName : "Mark"
}
]I want to be able to combine the Obejcts with the same ID and make an object of the different properties in those objects so the result would look something like
var ModifiedStudents = [
{
ID : 1,
Name : "John Doe",
Sponsers : [
{
SponserID : 421,
SponserName : "Mark"
},
{
SponserID : 341,
SponserName : "James"
},
]
},
{
ID : 2,
Name : "James Law",
SponserID : 421,
SponserName : "Mark"
}
]Lodash remains a highly useful bag of utilities, but with the advent of ES6 some of its use cases are less compelling.
For each object (person) in the first array, find the object in the second array with matching ID (see function findPerson). Then merge the two.
function update(array1, array2) {
var findPerson = id => array2.find(person => person.id === id);
array1.forEach(person => Object.assign(person, findPerson(person.id));
}
For non-ES6 environments, rewrite arrow functions using traditional syntax. If Array#find is not available, write your own or use some equivalent. For Object.assign, if you prefer use your own equivalent such as _.extend.
This will merge all properties from array2 into array1. To only merge eyeColour:
function update(array1, array2) {
var findPerson = id => array2.find(person => person.id === id);
array1.forEach(person => {
var person2 = findPerson(person.id));
var {eyeColour} = person2;
Object.assign(person, {eyeColour});
});
}
Just noticed Paul answered while I was working on my answer but I'll add my very similar code anyway:
var getEyeColour = function (el) { return _.pick(el, 'eyeColour'); }
var out = _.merge(arr1, _.map(arr2, getEyeColour));
DEMO
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');
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; }