澄清减少在javascript中创建过滤器

时间:2016-05-06 21:35:59

标签: javascript arrays functional-programming

我学术目的的主要目标是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;
&#13;
&#13;

2 个答案:

答案 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);
}

出现黑洞......

reducehigher-order functions的带领下,你现在站在lambda calculusfunctional programming深邃大海的海岸上。如果你感到非常热心,你可以探索curryingcombinators如何更加戏剧性地改变这个定义。

以下代码是用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