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

时间:2016-06-02 19:00:44

标签: arrays json underscore.js lodash

我有以下对象:

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 },
]

但现在我想回来:

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

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

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

干杯。

4 个答案:

答案 0 :(得分:6)

使用groupBy代替reduce进行初始分组的已接受答案的扭曲:

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

答案 1 :(得分:4)

有趣的是不是直截了当,因为想要按键累积值,而是希望将键作为属性键的值。所以有点像逆映射reduce:

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();

答案 2 :(得分:1)

您可以使用map()uniq()获取所有唯一names,然后使用map()每个名称使用sumBy()获取各自的总和。

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>
&#13;
&#13;
&#13;

这是非es6版本:

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

答案 3 :(得分:0)

这是一个简单的非 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)