Javascript reduce函数中的可选参数

时间:2015-03-21 08:58:29

标签: javascript higher-order-functions

我正致力于在Javascript中编写reduce函数。当没有传递start(计数器)的参数时,该函数正常工作,但是当传递一个起始值时,我得到一个不正确的答案。例如,如果我将([1,2,3], function(a,b){return a + b;}, 0)传递给函数,则输出5而不是6.如果没有传递第三个参数(起始值),我想要"总计"使用shift设置为数组中第一个元素的变量,然后删除该元素,不再计算。

function reduce(arr, func, start) {
    var total = start || arr.shift();
    each(arr, function(item) {
        total = func(item, total);
    });
    return total;
};

(每个都是我编写的一个简单的forEach函数,工作正常。)我尝试了很多不同的变体,而且我似乎无法让它工作。没有传递第三个参数时,是否有更好的方法设置总变量?

3 个答案:

答案 0 :(得分:2)

我不会修改原始数组,这在reduce函数中是一个相当不理想的副作用。

明确也比隐含更好。毕竟,你可能想要使用假值#34; start&#34 ;.

function reduce(arr, func, start) {
    var total; i;
    if (typeof start === "undefined") {
        total = arr[0];
        i = 1;
    } else {
        total = start;
        i = 0;
    }
    for (; i < arr.length; i++) {
        total = func(arr[i], total);
    }
    return total;
};

答案 1 :(得分:2)

只是为了好玩,一个递归实现(将在ES6中使用TR优化进行优化):

function reduce(arr, func, start) {
    if (arr.length == 0) {
        return start;
    }

    var accum = typeof start == 'undefined' ? arr[0] : func(start, arr[0]);

    return reduce(arr.slice(1), func, accum);
}

console.log(reduce([1,2,3], function(a,b){return a + b;}));

JSFiddle:http://jsfiddle.net/k3kuoz3w/1/

<强> UPD

在评论@Tomalak中提到,此解决方案将在每次迭代时创建一个数组。

为了更好玩,这里的解决方案不会产生不必要的副本:

function reduce(arr, func, start, i) {
    if (arr.length == i) {
        return start;
    }

    i = i || 0;

    var accum = typeof start == 'undefined' ? arr[i] : func(start, arr[i]);

    return reduce(arr, func, accum, i + 1);
}

http://jsfiddle.net/k3kuoz3w/2/

UPD 2

最后一个解决方案(我保证)封装了前面代码中公开的脏i

function reduce(arr, func, start) {
    function real_reduce(arr, func, start, i) {
        if (arr.length == i) {
            return start;
        }

        var accum = typeof start == 'undefined' ? arr[i] : func(start, arr[i]);

        return real_reduce(arr, func, accum, i + 1);
    }

    return real_reduce(arr, func, start, 0)
}

http://jsfiddle.net/k3kuoz3w/3/

答案 2 :(得分:0)

另一个简单的递归函数

较新的:

function reduce(arr, fn, start) {
  if(typeof start !== "undefined") {
    return recur([start].concat(arr), 0);
  } else {
    return recur(arr,0)
  }
  function recur(arr, index) {
    if(arr.length === 0) {
      return RangeError();
    } else if(index + 1 === arr.length) {
      return arr[index];
    } else {
      return fn(arr[index] , recur(arr, index + 1));
    }
  }
}
console.log(reduce([1, 2, 3], function(a, b) {return a + b}))
console.log(reduce([1, 2, 3], function(a, b) {return a + b}, 9))
console.log(reduce([1, 2, 3], function(a, b) {return a + b}, 0))
console.log(reduce([1, 2, 3], function(a, b) {return a * b}, 1))
console.log(reduce([], function(a, b) {return a + b}, 0))

旧评论(不要参考):

reduce(arr,fn,start){   if(typeof start === undefined){     return reduce(arr,fn,0)   } else {     var total = start;     each(arr,function(item){         total = func(item,total);     });     返回总数;   } }