我学术目的的主要目标是solve this problem,而且我所做的大部分工作。另外,我想通过不了解代码的错误来确保我没有错过reduce的基本部分。
这就是我解决它的方法,我已经附加了我的reduce函数以及filter函数。我相信我的reduce函数可以工作,但是我的过滤功能并不是很好,因为我无法通过我的测试用例。
1)为什么我没有击中阵列的最后一个元素?
我注意到,在降低功能的任何一点,prev和curr实际上永远不会返回5。我在reduce函数中遗漏了什么吗?
myArray = [1,2,3,4,5];
function each(collection, action){
if(Array.isArray(collection)){
for(var i = 0; i < collection.length; i ++){
action(collection[i]);
}
}
else if(typeof(collection) === "object"){
for (var property in collection){
action(collection[property]);
}
}
}
function reduce(collection, combine, start){
each(collection, function(element){
if(start === undefined){
return start = element;
}
else {
return start = combine(start, element);
}
});
return start;
}
function filterR(collection, predicate){
var aR = [];
reduce(collection, function(prev, curr){
if(predicate(prev)){
aR.push(prev);
}
if(predicate(curr)){
aR.push(curr);
}
});
return aR;
}
console.log(filter(myArray, function(val){return val % 5 === 0;})); //expected [5]
console.log(filter(myArray, function(val){return val <= 5;})); //expected [1,2,3,4,5]
&#13;
答案 0 :(得分:0)
我无法诊断您的问题,因为我不知道您的
each
程序是什么。无论如何,没关系;你是在思考它。
reduce
手动实施非常简单。
function reduce(f, start, arr) {
if (arr.length === 0)
return start;
else
return reduce(f, f(start, arr[0]), arr.slice(1));
}
// example
function add(x,y) { return x+y; }
reduce(add, 0, []); //=> 0
reduce(add, 0, [1,2,3]); //=> 6
我看到你试图在没有可选起始值的情况下支持某种缩减。如果你的reduce函数被认为是total function,这是不可能的。起始值必需。不要试图变得聪明。
现在使用filter
reduce
function filter(f, arr) {
return reduce(function(result, x) {
if (f(x))
return result.concat([x]);
else
return result;
}, [], arr);
}
您的示例
var myArray = [1,2,3,4,5];
filter(function(val){return val % 5 === 0;}, myArray)
//=> [5]
filter(function(val){return val <= 5;}, myArray)
//=> [1, 2, 3, 4, 5]
如果您想了解更多信息......
还有其他方法可以实现reduce
。你可以做的一个改进是将递归放在tail position中。当JavaScript引擎支持尾部调用消除(使用ES6)时,这会阻止reduce
堆栈溢出,因为arr
的值非常大。
function reduce(f, start, arr) {
function loop(result, arr) {
if (arr.length === 0)
return result;
else
return loop(f(result, arr[0]), arr.slice(1));
}
return loop(start, arr);
}
出现黑洞......
在reduce
和higher-order functions的带领下,你现在站在lambda calculus和functional programming深邃大海的海岸上。如果你感到非常热心,你可以探索currying和combinators如何更加戏剧性地改变这个定义。
以下代码是用ES6编写的
// U-combinator
const U = f=> f(f);
// Y-combinator
const Y = U (h=> f=> f (x=> h (h) (f) (x)));
// reduce
const reduce = f=> Y(h=> start=> arr=>
arr.length === 0
? start
: h (f (start) (arr[0])) (arr.slice(1)));
// filter
const filter = f=>
reduce(result=> x=>
f(x) ? result.concat([x]) : result) ([]);
// your examples again...
var myArray = [1,2,3,4,5];
filter (x=> x % 5 === 0) (myArray) //=> [5]
filter (x=> x <= 5) (myArray) //=> [1, 2, 3, 4, 5]
答案 1 :(得分:-1)
为什么我没有击中阵列的最后一个元素?
我不知道。你的每个功能可能都是一个错误,这里没有发布。但是,由于你的功能有一些更多的缺陷,我将添加一个有效的实现。
我注意到,在降低功能的任何一点,prev和curr实际上永远不会返回5。
prev和curr永远不会返回任何东西,它们是争论。而那个特定的功能本身也没有任何回报。
首先start === undefined
没有正确检查以确定是否要使用第一个(当前)元素初始化结果值。 undefined
在那个地方是意想不到的,甚至是不受欢迎的价值,但它实际上非常好。因此,通过该检查,您的reduce函数可能会在集合的中间重新开始。
只需看看您在过滤器中使用的前面提到的功能。此函数返回undefined
(作为下一次迭代的值);),以便{1}}在代码中始终为prev
。
然后,reduce对你的过滤器功能毫无意义,至少你使用它的方式。您将其用作undefined
。
each