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

时间:2014-04-24 10:25:16

标签: 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 }
    ]
  }
];

问题:我想弃去所有的金额'对象一起获取[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]);

到目前为止,使用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();

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

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

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

1 个答案:

答案 0 :(得分:5)

  

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

不幸的是,不完全是partialRight因此而被打破。如果我们查看the docs,他们已经指出了会发生什么:

  

将部分参数附加到提供给新函数的那些

在源代码中查看确认新函数不仅仅期望一个参数,而是任意数量的参数,只是将部分给定的参数附加到它们。由于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 ] ]
  

它只适用于显式闭包函数

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

.map(function(a) { return _.pluck(a, 'Amount'); })
  

有没有办法让它更简洁?

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

.map(_.createCallback(_.partialRight(_.pluck, 'Amount'), null, 1))

不确定这是否更好。