在计算一个值时,使用reduce
是最好的选择。它并不特别复杂。想象一下你想要对每个元素求和。
[1,2,3,4,5].reduce((a,e) => a+e, 0); // => 15
而 reduce
实际上可以使用递归实现:
Array.prototype.myReduce = function(proc,init) {
var arr = this;
var nLen = this.length;
function helper(acc, nIndex) {
return nIndex >= nLen ?
acc :
helper(proc(acc, arr[nIndex]), nIndex+1);
}
return helper(init, 0);
}
[1,2,3,4,5].myReduce((a,e) => a+e, 0);
请注意,实际的实现不会使用递归,因为JS不优化尾递归,因此循环结构将更有效。例如,Ramda是一个函数库,它提供了使用组合制作程序的手段,但在Ramda中映射和缩减是使用循环实现的。
编辑
如果您的结构实际上不是数组,而是类似于链接列表,则需要通过检查是否为单例空元素来检查是否处于末尾。这里有一个使用reduce实现单向链表的示例,它看起来像本答案中的先前访问器和停止条件:
function List() {}
List.prototype.cons = function(a) {
var c = new List();
c.a = a;
c.d = this;
return c;
}
List.prototype.car = function() {
return this.a;
}
List.prototype.cdr = function() {
return this.d;
}
List.prototype.reduce = function(proc, init) {
function helper (lst, acc) {
return lst === emptyList ?
acc :
helper(lst.cdr(), proc(acc, lst.car()));
}
return helper(this, init);
}
List.prototype.length = function() {
return this.reduce(acc => acc+1, 0);
}
List.prototype.reverse = function() {
return this.reduce((acc, a) => acc.cons(a),emptyList);
}
window.emptyList = new List();
var example = emptyList.cons(1).cons(2).cons(9);
example.reduce((a,e)=>a+e,0);
example.length();
example.reverse();
count
设置为初始值,它将等于undefined
。 - Jongwarevar lengthOfA = a.reduce(count => count+1, 0);
- Thomasconst length = arr => arr.shift() ? 1 + length(arr) : 0
- Xaqron