Javascript减少累加器解释

时间:2017-08-15 15:08:21

标签: javascript reduce accumulator

谁可以用简单的英语解释下面的累加器 acc 结构?

return arr1.reduce(function(acc, curr){  
  var last = acc[acc.length-1];  
  if(acc.length > 0 && curr[1]===last[1]) {
    last[0] += curr[0];
  }
  else acc.push(curr);
  return acc;
  }, []);
}

此reduce方法可用于解决FreeCodeCamp" Inventory Update"赋值,作为高级算法脚本课程的一部分。

链接:https://www.freecodecamp.org/challenges/inventory-update。 一个是需要更新库存数组(arr1)中的现有项目,其中包含"新交付"阵列。

两个测试数组,分别是现有广告资源 curInv 和新投放 newInv ,如下所示:

var curInv = [
[21, "Bowling Ball"],
[2, "Dirty Sock"],
[1, "Hair Pin"],
[5, "Microphone"]
];

var newInv = [
[2, "Hair Pin"],
[3, "Half-Eaten Apple"],
[67, "Bowling Ball"],
[7, "Toothpaste"]
];

在找到几篇关于Javascript reduce方法的优秀文章(例如this post和一个关于egghead.io的精彩视频课程),并以某种方式感知它有用的力量之后,我会按如下方式阅读该方法:

"通过首先创建一个空数组[](初始值),然后应用以下回调函数来减少库存数组:
如果库存数组当前不为空(长度大于零),并且当前处理的项目的名称(curr的索引0可以读取" Bowling Ball"例如)与最后一项相同要更新的库存数组,然后更新库存数组中此项目的数量 最后一项在if语句的正上方定义,如下所示:将累积数组的当前长度计算到现在,减去1,并使用该值索引累积的数组。然后将该索引处的元素分配给变量' last'。 另一方面,如果库存为空,则完全添加新项目,即:项目名称和金额。 现在返回新累积的数组。"

如何使用累加器的长度 - 1 来使acc实际累积? (原谅头韵)

我想我最了解这种简化方法是如何构建的,但请在我误读的任何地方纠正我,除了这个特殊的 使用acc.length-1。

干杯,k。

3 个答案:

答案 0 :(得分:0)

您是否在询问此部分?

var last = acc[acc.length-1]; 

如果是这样,acc.length-1是因为在数组中

acc = [a,b,c,d]
acc.length is equal to 4

要访问元素d,您将通过

访问它
acc[3];  //which equals d

这是因为我们计算的位置是0,1,2,3

答案 1 :(得分:0)

实际的解决方案包括连接和排序两个数组,然后才减少它们。 在这种情况下,每当我们评估一个新项目时,如果它的名称不等于最后一个累加项目,则表示它是一个新项目。

使用您的示例,我们减少的列表是:

[
  [ 21, 'Bowling Ball' ],
  [ 67, 'Bowling Ball' ],
  [ 2, 'Dirty Sock' ],
  [ 1, 'Hair Pin' ],
  [ 2, 'Hair Pin' ],
  [ 3, 'Half-Eaten Apple' ],
  [ 5, 'Microphone' ],
  [ 7, 'Toothpaste' ]
]

所以当我们遇到第二个项目时,累加器中的最后一个值是[21, 'Boweling Ball'],当我们比较字符串时,我们会进入第一个条件。

答案 2 :(得分:0)

tl;dr:看看这个REPL example


Reduce 能够将原始数组减少到函数中定义的值。

例如,如果我们有一个整数数组想要计算它的总和,我们可以使用 reduce 来实现。

当然,您可能会问为什么要使用 reduce 而不是 for loop

reduce 是更好选择的主要原因是因为我们作为参数传递的 reducer 函数是 pure。这意味着,计算结果不需要“额外”或“外部”变量。在 for 循环中,我们需要有一个 totalSum 变量来计算结果,而在 reduce 版本中则不需要。

回到 OP 的例子,这就是我们如何构造 reduce 以按同名邀请分组:

// reduce example
const reducer = (accumulator, currentValue) => {
    if (accumulator.length === 0) {
        accumulator.push(currentValue);
        return accumulator;
    }

    const index = accumulator.findIndex(el => el[1] === currentValue[1]);

    if (index !== -1) {
        accumulator[index][0] += currentValue[0];
        return accumulator;
    }
    accumulator.push(currentValue);
    return accumulator
};

这是 for 循环的等效版本:

// for loop example
let withForLoop = (input) => {
    let res = [];
    for (let i = 0; i < input.length; i++) {
        let currInput = input[i];
        const index = res.findIndex(el => el[1] === currInput[1]);
        if (index !== -1) {
            res[index][0] += currInput[0];
            continue;
        }
        res.push(currInput);
    }
    return res;
}

如果您不熟悉 reduce,可能需要一些时间才能完全理解它。它的使用几乎总是可以减少容易出错的应用程序,因此我主张花一些时间来充分了解它的功能以及何时使用它。