减少键上的对象数组并将值求和到数组中

Reduce array of objects on key and sum value into array

我有以下对象:

data = [
  { name: 'foo', type: 'fizz', val: 9 },
  { name: 'foo', type: 'buzz', val: 3 },
  { name: 'bar', type: 'fizz', val: 4 },
  { name: 'bar', type: 'buzz', val: 7 },
];

并使用了 lodash 地图:

result = _.map(data, function item, idx){
  return {
    key: item[key],
    values: item.value,
  }
}

这导致:

[
  { key: foo, val: 9 },
  { key: foo, val: 3 },
  { key: bar, val: 4 },
  { key: bar, val: 7 },
]

但现在我正在尝试 return:

[
  { key: 'foo', val: 12 },
  { key: 'bar', val: 11 },
]

我尝试使用 reduce,它似乎只输出到单个对象,然后我可以将其转换回数组,但我觉得必须有一种优雅的方式来使用 lodash 从我的源数据直接转到我想要的结果没有所有的中间步骤。

我认为 正在解决我的确切问题,但将对象转换为上面概述的所需对象数组似乎需要大量工作。

干杯。

有趣的是,这不是直截了当的,因为想通过键累加值,但又希望键作为 属性 键的值。所以有点像逆映射减少:

var result = 
    _.chain(data)
        .reduce(function(memo, obj) {
            if(typeof memo[obj.name] === 'undefined') {
                memo[obj.name] = 0;
            } 
            memo[obj.name] += obj.val;
            return memo;
        }, {})
        .map(function (val, key) {
            return {key: key, val: val};
        })
        .value();

为了 es6 的简洁性:

_.chain(data)
    .reduce((memo, obj) => {
        memo[obj.name = obj.val] += obj.val;
        return memo; 
    }, {})
    .map((val, key) => ({key, val}))   
    .value();

对使用 groupBy 而不是 reduce 进行初始分组的已接受答案的扭曲:

var result = _.chain(data)
    .groupBy('name')
    .map((group, key) => ({ key, val : _.sumBy(group, 'val') }))
    .value();

您可以使用 map() and uniq(), and then map() each name to get their respective sums using sumBy().

获得所有独特的 names
var result = _(data)
  .map('name')
  .uniq()
  .map(key => ({ 
    key, 
    val: _(data).filter({ name: key }).sumBy('val')
  }))
  .value();

var data = [
  { name: 'foo', type: 'fizz', val: 9 },
  { name: 'foo', type: 'buzz', val: 3 },
  { name: 'bar', type: 'fizz', val: 4 },
  { name: 'bar', type: 'buzz', val: 7 }
];

var result = _(data)
  .map('name')
  .uniq()
  .map(key => ({ 
    key, 
    val: _(data).filter({ name: key }).sumBy('val')
  }))
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>

这里是非es6版本:

var result = _(data)
  .map('name')
  .uniq()
  .map(function(key) { 
    return {
      key: key, 
      val: _(data).filter({ name: key }).sumBy('val')
    };
  })
  .value();

这是一个简单的非 lodash 版本。

const data = [{
    name: 'foo',
    type: 'fizz',
    val: 9
  },
  {
    name: 'foo',
    type: 'buzz',
    val: 3
  },
  {
    name: 'bar',
    type: 'fizz',
    val: 4
  },
  {
    name: 'bar',
    type: 'buzz',
    val: 7
  },
]

const result = data.reduce((acc, curr) => {
  const index = acc.findIndex(item => item.name === curr.name)
  index > -1 ? acc[index].val += curr.val : acc.push({
    name: curr.name,
    val: curr.val
  })
  return acc
}, [])

console.log(result)