Reduce - Part 3 of 函数式编程


  • administrators

    虽然reduce, map, filter常常被放在一起介绍,但是reduce的用法比较特殊,也比较难掌握,虽然在函数式编程的第一章,我们介绍过reduce,但是我还是觉得有必要在这里更加深入的介绍一下。

    基本上我可以用下面表达式来描述reduce

    const arr=[1,2,3];
    function f (a, b) { return a + b; }
    
    arr.reduce (f) = f(f(arr[0], arr[1]), arr[2]);
    

    分解开来,就是:

    const result = f(arr[0], arr[1]) = f(1, 2) = 3;
    result = f(result, arr[2]) = f(3,3) = 6;
    

    其实reduce还有第二个参数,也就是所谓的初始值,如果我们定义了这个值,那么,第一次传入给处理函数的参数就是不是数组的前两个成员,而是,这个初始值和数组的第一个成员。表达式如下:

    arr.reduce(f, INIT) = f(f(f(INIT, arr[0]), arr[1]), arr[2]);
    

    如果数组成员不是简单的数值或者字符串,那是这个初始值就变得很有用。

    看下面这个数组:

    const orders =[
      {amount: 1},
      {amount: 2},
      {amount: 3},
      {amount: 4}
    ]
    

    如果你用上面的reduce来计算总和就行不通了:

    const total = orders.reduce((x,y)=>x.amount + y.amount);
    

    虽然第一次调用求和函数,等到结果 = orders[0].amount + orders[1].amount = 3, 但是第二次我们把3 和 orders[2] 传给求和函数,我们就无法得到正确结果,因为3.amount是不存在的。
    解决这个问题,我们需要用到初始值,如下:

    const result2 = arr.reduce(
      (x,y) => {
        return x + y.amount;
      }, 1
    );
    

    看Pen: https://codepen.io/adamcai/pen/aQXEqB?editors=0010