Underscore/Lo-Dash链中的应用函子 - 如何在地图内映射?

ane*_*ane 2 javascript functional-programming underscore.js lodash

我有一个这样的嵌套对象:

var itemsWithQuantities = [
  {
    Identifier: 'SomethingWithQuantities1',
    Quantities: [
      { Name: 'Quantity 1', Amount: 4 },
      { Name: 'Quantity 2', Amount: 1 },
      { Name: 'Quantity 3', Amount: 3 }
    ]
  },
  {
    Identifier: 'SomethingWithQuantities2',
    Quantities: [
      { Name: 'Quantity 1', Amount: 3 },
      { Name: 'Quantity 2', Amount: 2 },
      { Name: 'Quantity 3', Amount: 5 }
    ]
  }
];
Run Code Online (Sandbox Code Playgroud)

问题:我想将所有'Amount'对象折叠在一起,以获得[7, 3, 8],将其视为该Amount字段的水平和.我想用方法链干净利落地做这件事.

没有方法链接的现有解决方案是这样的:

var amountSumsNoChain = _.reduce(_.map(itemsWithQuantities, function(item) {
  return _.pluck(item.Quantities, 'Amount');
}), function (prevQ, nextQ) {
  return [
    prevQ[0] + nextQ[0],
    prevQ[1] + nextQ[1],
    prevQ[2] + nextQ[2]
  ];
}, [0, 0, 0]);
Run Code Online (Sandbox Code Playgroud)

到目前为止,使用Lo-Dash的最干净的解决方案_.partialRight,我得到的是:

var amountSumsChain = _.chain(itemsWithQuantities)
  .pluck('Quantities')
  .map(function(a){return _.partialRight(_.pluck, 'Amount')(a);}) 
  .reduce(function(p,c){return [p[0] + c[0], p[1] + c[1], p[2] + c[2]];}).value();
Run Code Online (Sandbox Code Playgroud)

在第三行,通过.map调用,有没有办法简化该行更多?

为什么我不能使用.map(_.partialRight(_.pluck, 'Amount'))_.partialRight应该返回一个函数,它需要一个pluck参数,正如你所看到的,它可以在上面的方法链中工作,但是有一个显式的闭包函数.有没有办法让它更简洁?

JSBin:http://jsbin.com/qimekapu/1/edit?js,console

Ber*_*rgi 5

为什么我不能使用.map(_.partialRight(_.pluck, 'Amount'))_.partialRight应该返回一个期望一个参数的函数pluck.

不幸的是,不完全partialRight是为了这个目的而被打破.如果我们查看文档,他们已经指出了会发生什么:

局部参数被附加到那些提供给新的功能

在源代码中查看一下,确认新函数不只是期望一个参数,而是任意数量的参数,只是将部分参数附加到它们.并且因为map它使用项,索引和集合调用它的回调,那些碰巧传递给pluck:

_.map([[{Amount:3}[], _.partialRight(_.pluck, 'Amount'))
// is actually equivalent to
[ _.pluck([{Amount:3}], 0, [[{Amount:3}]], 'Amount') ]
// which will pluck the "0" property, not "Amount":
[ [ undefined ] ]
Run Code Online (Sandbox Code Playgroud)

它只适用于显式闭包函数

[它实际上没有关闭,因为它没有自由变量.]是的,该函数有效,因为您只显式地将一个参数传递给部分应用的函数.实际上你不再需要部分应用它,但可以使用

.map(function(a) { return _.pluck(a, 'Amount'); })
Run Code Online (Sandbox Code Playgroud)

有没有办法让它更简洁?

要避免使用函数表达式,可以使用createCallback限制参数计数:

.map(_.createCallback(_.partialRight(_.pluck, 'Amount'), null, 1))
Run Code Online (Sandbox Code Playgroud)

但不确定这是否更好.