汇总具有相同属性名称的对象的值

时间:2018-11-01 19:34:22

标签: javascript arrays object

我有一个充满对象的数组。以下示例显示了对象的结构。

let array = [
  { 
    data: [{name:'a', value:20}, {name:'b', value:10}, {name:'c', value:5}]
  },
  { 
    data: [{name:'d', value:20}, {name:'a', value:10}, {name:'e', value:40}]
  },
  { 
    data: [{name:'b', value:30}, {name:'a', value:5}]
  }
];

我试图遍历所有数据值并汇总所有相同的字母,然后在新数组中汇总这些值。因此,新数组应如下所示:

let array = [{name:'a', value:35}, {name:'b', value:40}, {name:'c', value:5}, {name:'d', value:20}, {name:'e', value:40}];

这是我目前的做法,但我无法使其正常工作。

let prevData = '';
let summarizedArray = [];
for(let i = 0; i < array.length; i++) {
  for(let j = 0; j < array[i].data.length; j++) {

    if(prevData === array[i].data[j].name) {
      let summarized = {
        name: array[i].data[j].name;
        value: prevData.value + array[i].data[j].value;
      }
      summarizedArray.push(summarized);
    }

    prevData = array[i].data[j]; 
  }
}

//编辑示例:

let array = [
  { 
    data: [{name:'a', value1:20, value2:90, value3:'foo'},
           {name:'b', value1:30, value2:20, value3:'boo'}]
    },
    data: [{name:'c', value1:5, value2:10, value3:'goo'},
           {name:'a', value1:30, value2:20, value3:'foo'}]
    },
  { 
];

这些值应使用相同的名称捆绑在一起。应该将Value1和Value2的值相加,并且每个名称的Value3始终相同。

所以结果应该像这样:

let result = [{name:'a', value1:50, value2:110, value3:'foo'},
              {name:'b', value1:30, value2:20, value3:'boo'},
              {name:'c', value1:5, value2:10, value3:'goo'}
            ];

1 个答案:

答案 0 :(得分:1)

您可以使用Map并收集所有值。稍后获取收集值的对象数组。

let array = [{ data: [{ name: 'a', value: 20 }, { name: 'b', value: 10 }, { name: 'c', value: 5 }] }, { data: [{ name: 'd', value: 20 }, { name: 'a', value: 10 }, { name: 'd', value: 40 }] }, { data: [{ name: 'b', value: 30 }, { name: 'a', value: 5 }] }],
    result = Array.from(
        array.reduce(
            (m, { data }) => data.reduce(
                (n, { name, value }) => n.set(name, (n.get(name) || 0) + value),
                m
            ),
            new Map
        ),
        ([name, value]) => ({ name, value }) 
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

对于更复杂的对象,在检查类型后,可以添加单个属性。

var array = [{ data: [{ name: 'a', value1: 20, value2: 90, value3: 'foo' }, { name: 'b', value1: 30, value2: 20, value3: 'boo' }] }, { data: [{ name: 'c', value1: 5, value2: 10, value3: 'goo' }, { name: 'a', value1: 30, value2: 20, value3: 'foo' }] }],
    result = Array.from(
        array.reduce(
            (m, { data }) => {
                data.forEach(o => {
                    var temp = m.get(o.name);
                    if (!temp) {
                        m.set(o.name, temp = {});
                    }
                    Object.entries(o).forEach(([k, v]) => {
                        if (k === 'name') return;
                        if (typeof v === 'number') {
                            temp[k] = (temp[k] || 0) + v;
                        } else {
                            temp[k] = v;
                        }
                    });
                });
                return m;
            },
            new Map
        ),
        ([name, value]) => Object.assign({ name }, value)
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }