Merging Array Objects With Same Properies
Solution 1:
Here is a pure ES6 function that collects the object values that are numeric, adding them up (which is what you seem to do), per unique label:
functionmapData(data) {
const grouped = newMap(data.map( ({label}) => [label, { label }] ));
for (let obj of data) {
let target = grouped.get(obj.label);
for (let [key, val] ofObject.entries(obj)) {
if (typeof val === 'number') {
target[key] = (target[key] || 0) + val;
}
}
}
return [...grouped.values()];
}
// Sample dataconst data = [{label: 'label-1',published: 1,draft: 2,id: 'some1'},{label: 'label-1',published: 2,status: 0,draft: 1,id: 'some4'},{label: 'label-2',published: 1,draft: 14,id: 'some2'},{label: 'label-2',published: 12,status: 0,draft: 14,id: 'some3'}];
console.log(mapData(data));
.as-console-wrapper { max-height: 100%!important; top: 0; }
If you have numeric properties that you wanted to exclude, then it might be better to have an explicit set of properties you are interested in:
const props = newSet(['status', 'published', 'draft']);
// ... etc//if (props.has(key)) {
target[key] = (target[key] || 0) + val;
}
// ...
Solution 2:
Lodash
_.groupBy()
by the label, _.map()
the groups, and merge each group using _.mergeWith()
, and _.omit()
the id. When merging the groups, if the current value is a number, sum the current and new values, if not return undefined
- If customizer returns undefined, merging is handled by the method instead.
const arr = [{"label":"label-1","published":1,"draft":2,"id":"some1"},{"label":"label-1","published":2,"status":0,"draft":1,"id":"some4"},{"label":"label-2","published":1,"draft":14,"id":"some2"},{"label":"label-2","published":12,"status":0,"draft":14,"id":"some3"}]
const result = _(arr)
.groupBy('label')
.map((g) => _.omit(_.mergeWith({}, ...g, (objValue, srcValue) => _.isNumber(objValue) ? objValue + srcValue : undefined), 'id'))
.value()
console.log(result)
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ES6
Iterate the array with Array.reduce()
. On each iteration check if the accumulator (the Map) has the label, and if not add an empty object with the label as the key. Iterate the current object keys with Array.forEach()
, ignore id, and sum the numeric values. To get an array spread the Map.values()
:
const arr = [{"label":"label-1","published":1,"draft":2,"id":"some1"},{"label":"label-1","published":2,"status":0,"draft":1,"id":"some4"},{"label":"label-2","published":1,"draft":14,"id":"some2"},{"label":"label-2","published":12,"status":0,"draft":14,"id":"some3"}]
const result = [...arr.reduce((m, o) => {
m.has(o.label) || m.set(o.label, {})
const obj = m.get(o.label)
Object.keys(o).forEach((k) => {
if(k === 'id') return
obj[k] = typeof o[k] === 'number' ? (obj[k] || 0) + o[k] : o[k]
})
return m
}, newMap()).values()]
console.log(result)
Post a Comment for "Merging Array Objects With Same Properies"