使用Underscore/Lodash分组By和Sum

MyT*_*tle 11 javascript arrays object underscore.js lodash

我有这样的JSON:

[
  {
     platformId: 1,
     payout: 15,
     numOfPeople: 4
  },
  {
     platformId: 1,
     payout: 12,
     numOfPeople: 3

  },
  {
     platformId: 2,
     payout: 6,
     numOfPeople: 5

  },
  {
     platformId: 2,
     payout: 10,
     numOfPeople: 1
  },

]
Run Code Online (Sandbox Code Playgroud)

而且我希望platformId用和的payout和来对它进行分组numOfPeople.

即结果我想要这样的JSON:

[
  "1": {
     payout: 27,
     numOfPeople: 7
   },

  "2": {
     payout: 16,
     numOfPeople: 6
  }
] 
Run Code Online (Sandbox Code Playgroud)

我尝试使用underscore.js_.groupBy方法,它组合得很好,但我怎么能得到像上面演示的对象属性值的SUM?

DSa*_*Sav 25

这是针对此类问题的Lodash解决方案.它与Underscore类似,但具有一些更高级的功能.

const data = [{
    platformId: 1,
    payout: 15,
    numOfPeople: 4
  },
  {
    platformId: 1,
    payout: 12,
    numOfPeople: 3

  },
  {
    platformId: 2,
    payout: 6,
    numOfPeople: 5

  },
  {
    platformId: 2,
    payout: 10,
    numOfPeople: 1
  },
];

const ans = _(data)
  .groupBy('platformId')
  .map((platform, id) => ({
    platformId: id,
    payout: _.sumBy(platform, 'payout'),
    numOfPeople: _.sumBy(platform, 'numOfPeople')
  }))
  .value()

console.log(ans);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


the*_*eye 12

我尝试以功能方式执行此操作,结果就像这样

console.log(_.chain(data)
    .groupBy("platformId")
    .map(function(value, key) {
        return [key, _.reduce(value, function(result, currentObject) {
            return {
                payout: result.payout + currentObject.payout,
                numOfPeople: result.numOfPeople + currentObject.numOfPeople
            }
        }, {
            payout: 0,
            numOfPeople: 0
        })];
    })
    .object()
    .value());
Run Code Online (Sandbox Code Playgroud)


Rya*_*ley 7

本着 Lodash One Liners 的精神

  _.map(_.groupBy(your_list, 'group_by'), (o,idx) => { return { id: idx, 
summed: _.sumBy(o,'sum_me') }})
Run Code Online (Sandbox Code Playgroud)


elc*_*nrs 5

没有下划线你可以做到这一点:

var result = data.reduce(function(acc, x) {
  var id = acc[x.platformId]
  if (id) {
    id.payout += x.payout
    id.numOfPeople += x.numOfPeople
  } else {
    acc[x.platformId] = x
    delete x.platformId
  }
  return acc
},{})
Run Code Online (Sandbox Code Playgroud)

但是为什么你想要一个带数字键的对象?您可以将其转换回集合:

var toCollection = function(obj) {
  return Object.keys(obj)
    .sort(function(x, y){return +x - +y})
    .map(function(k){return obj[k]})
}

toCollection(result)
Run Code Online (Sandbox Code Playgroud)

请注意,对象是变异的,因此如果要维护原始数据,可以先克隆它们.

  • 接受答案,但不回答问题! (2认同)
  • 纯 JS 很烂,我认为 (2认同)
  • “为什么你想要一个带有数字键的对象”=&gt;因为在问题的上下文中,这些 id 也可以是 UUID 或任何唯一的 id。并且它们也不保证是连续的。因此,任何对好的 id 的假设都应该被放弃,而将 id 作为键又是一个很好的解决方案。 (2认同)

Lea*_*rtS 5

(在我看来)使用 underscore.js 的一个很好的功能方式:

var sum = function(t, n) { return t + n; };
_.mapObject(
    _.groupBy(data, 'platformId'),
    function(values, platformId) {
        return {
            payout: _.reduce(_.pluck(values, 'payout'), sum, 0),
            numOfPeople: _.reduce(_.pluck(values, 'numOfPeople'), sum, 0)
        };
    }
);
Run Code Online (Sandbox Code Playgroud)