将对象集合映射到汇总集合的单个对象

时间:2016-05-03 17:12:56

标签: javascript coffeescript lodash

上下文

我有这段代码:

  fspMap = _(cart.items)
    .filter( (r) -> r._id )
    .filter( (r) -> r.style.premium? )
    .groupBy( (r) -> r.style.premium.code )
    .value()
  console.log fspMap

其中cart.items是:

[ { _id: 'SA01-MBL0',
    style: 
     { __v: 4,
       _id: 'SA01',
       name: [Object] },
    quantity: 12,
    weight: 165 },
  { _id: 'EP01-BB1',
    quantity: 3,
    style: 
     { __v: 14,
       _id: 'EP01',
       premium: [Object],
       name: [Object] },
    weight: 155 },
  { _id: 'EP02-BL0',
    style: 
     { __v: 5,
       _id: 'EP02',
       premium: [Object],
       name: [Object] },
    quantity: 1,
    weight: 145 },
  { _id: 'EP02-BR0',
    style: 
     { __v: 5,
       _id: 'EP02',
       premium: [Object],
       name: [Object] },
    quantity: 1,
    weight: 145 } ]

问题

我试图获得一个按style.premium.code分组的新数组,这是我运行上述代码时得到的结果:

{ FSP01: [ { _id: 'EP01-BB1', quantity: 3, style: [Object], weight: 155 } ],
  FSP02: 
   [ { _id: 'EP02-BL0', style: [Object], quantity: 1, weight: 145 },
     { _id: 'EP02-BR0', style: [Object], quantity: 1, weight: 145 } ] }

但我想得到的是每个值的数量和权重,以获得类似:

{ 
  FSP01: { quantity: 3, weight: 155 },
  FSP02:{ quantity: 2, weight: 290 },
}

任何建议都非常感激。

2 个答案:

答案 0 :(得分:0)

给定一系列项目[item, item]

1)将数组缩减为_.reduce(arr, function() {}, {})的对象,因为您需要对象只有数量和重量

_.reduce(arr, function(result, item) {
}, {quantity: 0, weight: 0})

2)函数体应取每个项目并获取数量和重量并将其添加到初始值

_.reduce(items, function(result, item) {
  _.forIn(result, function (value, key) {
    result[key] += item[key]
  })
  return result
}, {quantity: 0, weight: 0})

3)最后为每个组执行此操作,因为您的组是一个对象,它将代码映射到您可以使用的项目数组_.mapValues

_.mapValues(groups, function (items) {
  return _.reduce(items, function(result, item) {
    _.forIn(result, function (value, key) {
      result[key] += item[key]
    })
    return result
  }, {quantity: 0, weight: 0})
})

最终解决方案

var groups = { FSP01: [ { _id: 'EP01-BB1', quantity: 3, style: [Object], weight: 155 } ],
  FSP02: 
   [ { _id: 'EP02-BL0', style: [Object], quantity: 1, weight: 145 },
     { _id: 'EP02-BR0', style: [Object], quantity: 1, weight: 145 } ] }


var g = _(groups)
  .mapValues(function (items) {
    return _.reduce(items, function (result, item) {
      _.forIn(result, function (value, key) {
        result[key] += item[key]
      })
      return result
    }, {quantity: 0, weight: 0})
  })
  .value()

document.write(JSON.stringify(g))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.min.js"></script>

答案 1 :(得分:0)

您可以将您的lodash链简化为以下内容:

<强> DEMO

var result = _(data)
  .filter('_id') // only items with _id property
  .filter('style.premium') // only items with style.premium object
  .groupBy('style.premium.code') // group by style.premium.code
  .mapValues((item) => ({ // map each object item
    quantity: _.sumBy(item, 'quantity'), // sum of quantity
    weight: _.sumBy(item, 'weight') // sum weight
  }))
  .value();