Skip to content Skip to sidebar Skip to footer

Merging Array Objects With Same Properies

i am doing one of my front end project and i have a situation where i have to merge/add objects present in the array based on some conditions. Conditions would be Only those Objec

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"