如何在数组中使用filter()函数过滤掉NaN、null、0和false?(JS)

15

我被要求在一个数组中过滤掉NaN, null, 0, false

幸运的是,我已经回答了这个问题。

function bouncer(arr) {
  function filterer(arr) {
     return arr > 0|| isNaN(arr) === true;
  }
  arr = arr.filter(filterer);
  return arr;
}

//example input
bouncer([0, 1, 2, 3, 'ate', '', false]); //output [1, 2, 3, 'ate']

但问题是,我真的不知道我是如何得出答案的,或者更准确地说,我不知道它是如何工作的。特别是在arr > 0方面,过滤器怎么知道arr已经在arr[1]、arr[2]等等,而没有使用循环来迭代所有数组。

或者可以简单地解释一下代码的工作原理。[我已经试图清楚地解释了。---]


1
你的代码有问题。对于像 -1 这样的值会失败... 请尝试使用 arr.filter(function(item) {return !!item;}) - Niet the Dark Absol
3
为什么不使用 [0, 1, 2, 3, 'ate', '', false].filter(Boolean) - Paul S.
是的,布尔过滤器是最好的选择,除非你想保留未定义的值。 - juvian
如果您删除 isNaN,那么 @MattBurland 的 ate 也将被删除,输出将为 [1, 2, 3] - Manwal
@Manwal:说得好,我漏掉了“ate”。 - Matt Burland
显示剩余2条评论
11个回答

79

如果让你在一个数组中过滤掉NaNnull0false,那么你的解决方案并不适用。

你的输入为:

bouncer([0, 1, 2, 3, 'ate', '', false, NaN]);

将获得以下输出:

[1, 2, 3, 'ate', NaN]

要过滤掉所有“假值”,您可以简单地使用 Boolean

function bouncer(arr) {
  return arr.filter(Boolean);
}

bouncer([0, 1, 2, 3, 'ate', '', false, NaN]);

输出:

[1, 2, 3, 'ate']
由于 Boolean 构造函数也是一个函数,它返回真值参数的 true 或虚值参数的 false。如果值被省略或为 0-0nullfalseNaNundefined 或空字符串 (""),对象的值为 false。所有其他值,包括任何对象或字符串 "false",都将创建一个初始值为 true 的对象。

易于理解且快速的解决方案。 - ethane

20

您也可以使用一个身份函数代替 Boolean

function bouncer(arr) {
  return arr.filter(x => x);
}

如何?你能解释一下吗? - messi
这个答案比被采纳的答案和目前最受欢迎的答案都要好。 - micapam
@messi 把它看作是 arr.filter(x => !!x),这样做的原因是 !!NaN 是 false。 - Fai

7

我也在研究自由编程阵营的Falsy Bouncer算法。我发现最简单的方法是:

function bouncer(arr) {
   return arr.filter(Boolean);
}

5
请查看Array.filter文档,特别留意回调函数的参数:

用于测试数组中每个元素的函数。调用时会传入参数 (element, index, array)。如果返回 true,则保留该元素,否则过滤掉。

所以在您的情况下,arr是元素(并且命名不当,因此会引起混淆)。Filter会循环遍历您的数组,并为每个项目调用回调函数,将当前位置的元素作为arr传递进去。

正如其他人在评论中指出的那样,对于负数值,您的过滤器回调逻辑实际上是有缺陷的,但是如果您知道您的数组永远不会包含负数值,则这可能不是问题(但是假设这一点可能是危险的)。

当然,在内部,这也是要循环遍历您的数组。如果您希望过滤(未排序的)数组而不触及每个元素,则是不可能的。请参考链接中的代码以了解它的运行方式(注意,这是一个可能与不同的javascript引擎不同的实现细节,但无论如何都会涉及循环),它会遍历您的数组、调用回调函数(注意参数),如果回调函数返回true,则将其推送到结果数组中。


1
谢谢!这就是我想知道的。在内部,它正在循环遍历您的数组。非常感谢!我会尝试改进我的变量命名! :) - Fhrey

3

filter() 方法通过提供的函数实现测试,创建一个新的数组,其中包含所有通过测试的元素。

由于在 JavaScript 中,falsenull0""undefinedNaN 都是假值,因此在测试时它们会返回false

function bouncer(arr) {
  var array = arr.filter(function(val){
    return val;
  });
  return array;
}

只有返回非假值的数值才会被添加到数组中。

1

如果基于这样一种假设,即当需要布尔类型时,所有不需要的元素都被转换为false,那么不是更加优雅吗?因此:

function clear (arr){
   var stripped = [];
   for (i = 0, len = arr.length; i < len; i++){
      if (arr[i])
         stripped.push(arr[i]);
   }
   return stripped;
}

0

由于我是编程的初学者,我的逻辑是使用原始布尔值来比较筛选出的项目,但这是在我阅读布尔对象参考文献之前,你会发现就像它写在那里的那样, “如果必要,将传递作为第一个参数的值转换为布尔值。如果省略值或为0、-0、null、false、NaN、undefined或空字符串(“”),则对象具有初始值false。所有其他值,包括任何对象或字符串“false”,都创建具有初始值true的对象。” 因此,逻辑上,由于过滤器返回值是否为true或false,您应该在它们为true时返回值。 此外,我还没有完全了解筛选方法,根据我的研究,我得到了更多的信息,我将在这里尝试解释。

重新定义方法(它已经存在,只是为了理解) 筛选方法接受一个称为谓词的函数,它是一个接收值并返回true或false的函数。

变量results是一个空数组,结果将使用push方法推送到其中。 然后我们使用forEach方法,这里的this应用于数组原型,这意味着您可以在定义的每个数组上使用filter方法,语法为array.method(args),在本例中为array.filter(args)。 一些资源 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

现在,我们将对数组中的每个项运行操作,并使用forEach方法将谓词函数应用于数组的每个项,如果返回true,则将其添加到结果中。

Array.prototype.filter = function(predicate){   
    var results = [];

    this.forEach(function(item) {   
        if (predicate(item)) {
            results.push(item);
        }

    });
};

//-------------------------------正确的解决方案---------------------------

function bouncer (arrToFilter){

    return arrToFilter.filter(Boolean);
}

//----------没有使用过滤方法的代码---------

function bouncerNoFilterMethod(arrToFilter){
    var results = [];

    arrToFilter.forEach(function(arrToFilter){
        if(arrToFilter){
            results.push(arrToFilter);
        }
    });

    return  results;    
}

console.log(bouncerNoFilterMethod([7, "ate", "", false, 9]));
console.log(bouncerNoFilterMethod(["a", "b", "c"]));
console.log(bouncerNoFilterMethod([false, null, 0, NaN, undefined, ""]));
console.log(bouncerNoFilterMethod([1, null, NaN, 2, undefined]));
console.log(bouncer([7, "ate", "", false, 9]));
console.log(bouncer(["a", "b", "c"]));
console.log(bouncer([false, null, 0, NaN, undefined, ""]));
console.log(bouncer([1, null, NaN, 2, undefined]));

希望这能帮助理解方法,最初不理解的是将函数谓词传递给方法的部分,如果我有错误,请建议更正。

0

看起来布尔值是“FreeCodeCamp”挑战的最简单解决方案,但尝试一些其他方法以了解“为什么”和“如何”可能会很有用。

function bouncer(arr) {
      return arr.filter(function(val){
        return val;
     });
    }

这个函数会对通过过滤器的所有内容进行评估,使用回调函数传递的功能(callback)去返回值。如果它没有返回值,例如null等,它将不会被包含在返回结果中。至少这种方法帮助我理解了为什么而不是只是通过测试。


0
测试数组中每个元素的函数。使用参数(元素,索引,数组)调用。返回true以保留元素,否则返回false。
如果你只想要解释。数组filter()的名字就像它所暗示的那样。如果条件不满足(false),则删除不需要的元素。
arr > 0|| isNaN(arr) === true
0,  false || false  //removed
1,  true || false  
2,  true || false
3,  true || false
'ate', false || true
'',   false|| false  // removed
false  false || false //removed

输出:

[1, 2, 3, "ate"]

在理解了filter()方法遍历所有数组元素后,这个例子展示了我的过滤器函数的工作原理,非常有帮助!谢谢! - Fhrey

0

我稍微修改了https://dev59.com/cVwZ5IYBdhLWcg3wC8f4#35327425,将所有没有数值的内容都设置为零

function zerofy(x){return (Boolean(x) && !isNaN(x.toString())) ? x : 0 ;}

测试通过

function clear (arr){
   var stripped = [];
   for (i = 0; i < arr.length; i++){
      stripped.push(zerofy(arr[i]));
   }
   return stripped;
}

clear(["written",13,0,-4,"5",true,false,undefined,null,NaN,Math.PI]);

结果返回

[0,13,0,-4,5,0,0,0,0,0,3.141592653589793]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接