Javascript 减少累加器解释

Javascript reduce accumulator explained

谁能用简单的英语解释下面的累加器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 的“库存更新”作业,作为其高级算法脚本课程的一部分。

需要用“新交付”数组中的新项目更新库存数组 (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 的精彩视频课程)之后,并以某种方式感受到它所带来的力量,我会阅读方法如下:

Reduce the inventory array, by creating an empty array [ ] first (the initial value), then applying the following callback function:

If the inventory array is currently not empty (has a length greater than zero), and the name of currently handled item (index 0 of curr could read "Bowling Ball" for example) is identical to the last item of the inventory array being updated, then update the amount of this item in the inventory array.

The last item is defined right above the if statement, as follows: take the present length of the accumulated array upto now, subtract 1, and use this value to index the accumulated array. The element at that index is then assigned to the variable 'last'.

On the other hand, if the inventory is empty, add the new item entirely, - that is: item name and amount. Now return the newly accumulated array."*

How is using the length - 1 of the accumulator useful to make acc actually accumulate? (pardon the alliteration)

我想我理解了这个 reduce 方法的大部分构建方式,但请纠正我任何误读的地方),除了这个特殊的 使用 acc.length-1.

干杯,k。

你问的是这个部分吗?

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 开始计算位置

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

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

[
  [ 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'],当我们比较字符串时,我们进入第一个条件。

tl;dr:看看这个 REPL example


Reduce 能够减少 原始数组为函数定义的值。

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

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

reduce 是更好选择的主要原因是因为我们作为参数传递的 reducer 函数是 pure。这意味着,计算结果不需要 'extra' 或 'external' 变量。在 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 的新手,您可能需要一些时间才能完全理解它。它的使用 几乎总是 导致应用程序更不容易出错,因此我主张花一些时间来充分了解它的功能以及何时使用它。