Merge duplicate objects in array of objects
I would probably loop through with filter
, keeping track of a map of objects I'd seen before, along these lines (edited to reflect your agreeing that yes, it makes sense to make (entry).data
always an array):
var seen = {};
data = data.filter(function(entry) {
var previous;
// Have we seen this label before?
if (seen.hasOwnProperty(entry.label)) {
// Yes, grab it and add this data to it
previous = seen[entry.label];
previous.data.push(entry.data);
// Don't keep this entry, we've merged it into the previous one
return false;
}
// entry.data probably isn't an array; make it one for consistency
if (!Array.isArray(entry.data)) {
entry.data = [entry.data];
}
// Remember that we've seen it
seen[entry.label] = entry;
// Keep this one, we'll merge any others that match into it
return true;
});
In an ES6 environment, I'd use seen = new Map()
rather than seen = {}
.Note: Array.isArray
was defined by ES5, so some quite older browsers like IE8 won't have it. It can easily be shimmed/polyfilled, though:
if (!Array.isArray) {
Array.isArray = (function() {
var toString = Object.prototype.toString;
return function(a) {
return toString.call(a) === "[object Array]";
};
})();
}
entry.data
an array, even if I didn't see two values for it, because consistent data structures are easier to deal with. I didn't do that above because your end result showed data
being just a string when there was only one matching entry.Live example (ES5 version):
var data = [ { label: "Book1", data: "US edition" }, { label: "Book1", data: "UK edition" }, { label: "Book2", data: "CAN edition" }];snippet.log("Before:");snippet.log(JSON.stringify(data, null, 2), "pre");var seen = {};data = data.filter(function(entry) { var previous;
// Have we seen this label before? if (seen.hasOwnProperty(entry.label)) { // Yes, grab it and add this data to it previous = seen[entry.label]; previous.data.push(entry.data);
// Don't keep this entry, we've merged it into the previous one return false; }
// entry.data probably isn't an array; make it one for consistency if (!Array.isArray(entry.data)) { entry.data = [entry.data]; }
// Remember that we've seen it seen[entry.label] = entry;
// Keep this one, we'll merge any others that match into it return true;});snippet.log("After:");snippet.log(JSON.stringify(data, null, 2), "pre");
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --><script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
merge duplicate objects in an array and add additional property
You can use reduce
to create a unique array that sets admin
property to true
for duplicate addresses as follows:
const addresses = [{name: 'Paul', id: 2}, {name: 'John', id: 1}, {name: 'John', id: 1}];
const result = addresses.reduce((acc, address) => { const dup = acc.find(addr => addr.id === address.id); if (dup) { dup.admin = true; return acc; } address.admin = false; return acc.concat(address);}, [])
console.log(result);
merge duplicate objects in an array and combine sub array of each object
I think, reduce()
would do the job:
const accounts = [{"Id":103,"accountList":[{}]},{"Id":103,"accountList":[{"tokenId":"5aasdasdsdnjn3434nadd","featureId":2840}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefaaa","featureId":2877}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefccc","featureId":2856}]}];
const result = [...accounts
.reduce((r, o) => {
const record = r.get(o.Id)||{}
r.set(o.Id, {
Id: o.Id,
accountList: [
...(record.accountList||[]),
...o.accountList.filter(o =>
Object.keys(o).length != 0)
]
})
return r
}, new Map())
.values()]
console.log(result);
.as-console-wrapper {min-height: 100%}
How to merge duplicate object parent items in array?
const data = [
{ "_id": { "month": 5, "year": 2021 }, "total_price": 145111500, "total_quantity": 7 },
{ "_id": { "month": 6, "year": 2021 }, "total_price": 98386000, "total_quantity": 5 },
{ "_id": { "month": 6, "year": 2021 }, "total_price": 32500000, "total_quantity": 3 }
];
const res = [...
// iterate over the list
data.reduce((map, item) => {
// construct key from _id
const key = `${item._id.month}-${item._id.year}`;
// get prev map value of key if exists
const prev = map.get(key);
// update map, if prev not found, set value as item, or update it with the added values
map.set(
key,
!prev
? item
: { ...item, total_price: prev.total_price + item.total_price, total_quantity: prev.total_quantity + item.total_quantity }
);
return map;
}, new Map)
// return map values
.values()
];
console.log(res);
Related Topics
What Is the Most Efficient Way to Reverse an Array in JavaScript
How to Auto-Slide the Window Out from Behind Keyboard When Textinput Has Focus
Problems with Circular Dependency and Oop in Angularjs
React Jsx: Selecting "Selected" on Selected <Select> Option
Why Doesn't Nodelist Have Foreach
Mocking a Useragent in JavaScript
How to Keep an JavaScript Object/Array Ordered While Also Maintaining Key Lookups
Why Are Es6 Classes Not Hoisted
Jquery Returning "Parsererror" for Ajax Request
Domnodeinserted Equivalent in Ie
Remove HTML Comments with Regex, in JavaScript
Why Let and Var Bindings Behave Differently Using Settimeout Function
How to Find a Reason Angularjs "Argument 'Myctrl' Is Not a Function, Got Undefined"