我正致力于在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函数,工作正常。)我尝试了很多不同的变体,而且我似乎无法让它工作。没有传递第三个参数时,是否有更好的方法设置总变量?
答案 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)
}
答案 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); }); 返回总数; } }