且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

合并具有相同属性的数组对象

更新时间:2022-10-19 14:05:10

这是一个纯ES6函数,它按唯一标签收集数字对象值,并将它们加起来(这似乎是您要做的): /p>

 function mapData(data) {
    const grouped = new Map(data.map( ({label}) => [label, { label }] ));
    for (let obj of data) {
        let target = grouped.get(obj.label);
        for (let [key, val] of Object.entries(obj)) {
            if (typeof val === 'number') {
                target[key] = (target[key] || 0) + val;
            }
        }
    }
    return [...grouped.values()];
}

// Sample data
const 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; } 

如果您要排除数字属性,那么***有一组您感兴趣的显式属性:

const props = new Set(['status', 'published', 'draft']);
// ... etc
//
if (props.has(key)) { 
    target[key] = (target[key] || 0) + val;
}
// ...

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 Objects having same label should be merged.
  • For objects which has same label, if object 'a' has properties which are present in b object as well, the value has to be added, else simply copy the property.

So my input would be

[
  {
    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'
  }
]

and the expect

    [
      {
        label: 'label-1',
        published: 3,
        draft: 4,
        status: 0
      },
{
        label: 'label-2',
        published: 13,
        draft: 28,
        status: 0
      }
    ]

Currently i am using the following code for achieving the same , but find it not tidy . Is there any way this could be achieved easily.

function mapData(data) {
    let groupData = _.groupBy(data, 'label');
    let stackBarData = [];
    Object.keys(groupData).forEach((key) => {
      if (groupData[key] && groupData[key].length > 0) {
        let temp = Array.from(groupData[key]).reduce((a, b) => {
          for (let property in b) {
            if (b.hasOwnProperty(property)) {
              if (property !== 'label' && property !== 'id' && property !== 'Others') {
                a[property] = (a[property] || 0) + b[property];
              } else {
                a[property] = b[property];
              }
            }
          }
          return a;
        }, {});
        stackBarData.push(temp);
      }
    });
    return stackBarData;
  }

Please help.

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:

function mapData(data) {
    const grouped = new Map(data.map( ({label}) => [label, { label }] ));
    for (let obj of data) {
        let target = grouped.get(obj.label);
        for (let [key, val] of Object.entries(obj)) {
            if (typeof val === 'number') {
                target[key] = (target[key] || 0) + val;
            }
        }
    }
    return [...grouped.values()];
}

// Sample data
const 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 = new Set(['status', 'published', 'draft']);
// ... etc
//
if (props.has(key)) { 
    target[key] = (target[key] || 0) + val;
}
// ...