I have 2 arrays of objects in JavaScript and would like to compare and merge the contents and sort the results by id. Specifically, the resulting sorted array should contain all objects from the 1st array, plus all objects from the 2nd array that have an id that's not in the 1st.
The following code seems to work (minus the sorting). But there must be a better, more succinct way to do this, particularly with features from ES6. I assume using a Set is the way to go, but not sure exactly how to implement.
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; // Resulting cars1 contains all cars from cars1 plus unique cars from cars2 cars1 = removeDuplicates(cars2); console.log(cars1); function removeDuplicates(cars2){ for (entry in cars2) { var keep = true; for (c in cars1) { if (cars1[c].id === cars2[entry].id) { keep = false; } } if (keep) { cars1.push({ id:cars2[entry].id, make:cars2[entry].make, model:cars2[entry].model, year:cars2[entry].year }) } } return cars1; }
One option with O(N)
complexity would be to make a Set
of the id
s in cars1
, then spread cars1
and a filtered cars2
into the ouput array, with the filter testing whether the id
in the car being iterated over in cars2
is included in the Set:
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; const cars1IDs = new Set(cars1.map(({ id }) => id)); const combined = [ ...cars1, ...cars2.filter(({ id }) => !cars1IDs.has(id)) ]; console.log(combined);
To sort
as well:
combined.sort(({ id: aId }, {id: bId }) => aId - bId);
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; const cars1IDs = new Set(cars1.map(({ id }) => id)); const combined = [ ...cars1, ...cars2.filter(({ id }) => !cars1IDs.has(id)) ]; combined.sort(({ id: aId }, {id: bId }) => aId - bId); console.log(combined);
You could use concat
, filter
and map
.
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; // Resulting cars1 contains all cars from cars1 plus unique cars from cars2 let ids = cars1.map(c => c.id); cars1 = cars1.concat(cars2.filter(({id}) => !ids.includes(id))) console.log(cars1);
Merge two arrays, put each array element in a map with their ids
and then create array from the map values.
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; cars = cars1.concat(cars2); let foo = new Map(); for(const c of cars){ foo.set(c.id, c); } let final = [...foo.values()] console.log(final)
You could take a Map
and take the item of them map first or the actual car.
var cars1 = [{ id: 2, make: "Honda", model: "Civic", year: 2001 }, { id: 1, make: "Ford", model: "F150", year: 2002 }, { id: 3, make: "Chevy", model: "Tahoe", year: 2003 }], cars2 = [{ id: 3, make: "Kia", model: "Optima", year: 2001 }, { id: 4, make: "Nissan", model: "Sentra", year: 1982 }, { id: 2, make: "Toyota", model: "Corolla", year: 1980 }], result = Array .from( [...cars1, ...cars2] .reduce((m, c) => m.set(c.id, m.get(c.id) || c), new Map) .values() ) .sort((a, b) => a.id - b.id); console.log(result);
You can use Object.values()
alongwith .concat()
and .reduce()
:
let cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; let cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; let merge = (arr1, arr2) => Object.values( arr1.concat(arr2).reduce((r, c) => (r[c.id] = r[c.id] || c, r), {}) ).sort((a, b) => a.id - b.id); console.log(merge(cars1, cars2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Assuming that the id's should be unique, this should work:
var union = (arr1, arr2) =>
{
var result = arr1.slice(0);
arr2.forEach((el) =>
{
if (getIndexByAttribute(arr1, 'id', el.id) < 0)
result .push(el);
});
return result;
};
var getIndexByAttribute = (array, attr, value) => {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
}
return -1;
}
But with your current examples cars1
and cars2
, you might need object camparison. Please see Object comparison in JavaScript [duplicate]
One approach can be using concat()
with the elements of cars2
whose ids are not already on cars1
, this can be checked using find()
. And finally sort()
the resulting array:
var cars1 = [ {id: 2, make: "Honda", model: "Civic", year: 2001}, {id: 1, make: "Ford", model: "F150", year: 2002}, {id: 3, make: "Chevy", model: "Tahoe", year: 2003}, ]; var cars2 = [ {id: 3, make: "Kia", model: "Optima", year: 2001}, {id: 4, make: "Nissan", model: "Sentra", year: 1982}, {id: 2, make: "Toyota", model: "Corolla", year: 1980}, ]; let res = cars1 .concat(cars2.filter(({id}) => !cars1.find(x => x.id === id))) .sort((a, b) => a.id - b.id); console.log(res);
.as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.