最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to filter() out NaN, null, 0, false in an array (JS) - Stack Overflow

programmeradmin9浏览0评论

I was asked to filter out NaN, null, 0, false in an array.

Luckily I have answered the question.

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']

but the thing is I really don't know how I came up with the answer or rather I don't know how it works. Specially on arr > 0 how did the filter know that arr is alread on arr[1], arr[2], etc.. without using a loop to iterate in all array.

or can simply just explain on how to code works. [I've tried to explain it clearly ---]

I was asked to filter out NaN, null, 0, false in an array.

Luckily I have answered the question.

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']

but the thing is I really don't know how I came up with the answer or rather I don't know how it works. Specially on arr > 0 how did the filter know that arr is alread on arr[1], arr[2], etc.. without using a loop to iterate in all array.

or can simply just explain on how to code works. [I've tried to explain it clearly ---]

Share Improve this question asked Aug 10, 2015 at 17:07 FhreyFhrey 1611 gold badge1 silver badge5 bronze badges 7
  • 1 Your code is wrong. It fails for values like -1... Try arr.filter(function(item) {return !!item;}) – Niet the Dark Absol Commented Aug 10, 2015 at 17:11
  • 3 @NiettheDarkAbsol why not [0, 1, 2, 3, 'ate', '', false].filter(Boolean) ? – Paul S. Commented Aug 10, 2015 at 17:12
  • yeah Boolean filter is the best unless you want to keep undefined – juvian Commented Aug 10, 2015 at 17:14
  • If you remove isNaN then @MattBurland ate will also remove output will be [1, 2, 3] – Manwal Commented Aug 10, 2015 at 17:25
  • @Manwal: Fair point, I missed ate in there. – Matt Burland Commented Aug 10, 2015 at 17:27
 |  Show 2 more comments

12 Answers 12

Reset to default 79

If you were asked to filter out NaN, null, 0, false in an array, then your solutions doesn't really work.

Your input of:

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

Will get the output of:

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

To filter out all 'falsy' values you can simply use Boolean:

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

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

Output:

[1, 2, 3, 'ate']

Since the Boolean constructor is also a function, it returns either true for ‘truthy’ argument or false for ‘falsy’ argument. If the value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has the value of false. All other values, including any object or the string "false", create an object with an initial value of true.

You can also use an identity function instead of Boolean.

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

I am also working on the Free Code Camp Falsy Bouncer Algorithm. I have found the simplest way to do it is:

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

Look at the docs for Array.filter. Notice in particular the arguments to the callback:

Function to test each element of the array. Invoked with arguments (element, index, array). Return true to keep the element, false otherwise.

So in your case arr is the element (and poorly named, hence your confusion). Filter loops through your array and for every item it calls you callback passing in the element at the current position as arr.

As others have pointed out in the comments, the logic of your filter callback is actually flawed for negative values, but that may not be an issue if you know that your array will never contain negative values (but that can be a dangerous thing to assume).

And, of course, internally, this is looping through your array. You can't filter your (unsorted) array without touching each element in the array. Look at the polyfil in the link to get an idea of how it might work (might because this is an implementation detail that may differ with different javascript engines, but will no doubt involve a loop somewhere), it loops through your array, calls the callback (note the arguments) and if the callback returns true, it gets pushed onto a results array.

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

Since false, null, 0, "", undefined and NaN are all Falsy values in JavaScript therefore they will return false when tested.

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

Only values which do not return false will be added to the array.

Wouldn't be more elegant to base on assumption that all unwanted elements are casted to false when boolean expected, so:

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

Function to test each element of the array. Invoked with arguments (element, index, array). Return true to keep the element, false otherwise

If you just want explanation. Array filter() as name suggest. Remove unwanted element if condition falls wrong (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

Output:

[1, 2, 3, "ate"]

Since i´m a beginner o coding, my logic went to use primitive Boolean´s to compare the item´s filtered, but this was before I have read the Boolean Object reference, you see is that like its written there, "The value passed as the first parameter is converted to a Boolean value if necessary. If value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object or the string "false", create an object with an initial value of true." So the logic since filter returns the value if it´s true or false, you should return values if they are true. Also, I didn´t learn everything about the filter method, for what I have researched, I have got a bit more of information, that I will try to explain here.´

redefining the method (it already exists, is just for understanding) the filter method accepts a function called a predicate, that is a function that receives a value and returns true or false.

The var results is an empty array where the results will be pushed with the push method. The we use a forEach method with this, (this, in this context is applied to the array prototype ,this means that you will have the filter method available on every array that you define, with the sintax of array.method(args) ins this case array.filter(args)) some resources https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Now we will run an operation in every item on the the array, with the forEach method, now we will apply the predicate function to itch item of the array and if it returns true, will add it to the results.

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

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

    });
};

//-------------------------------Correct Solution---------------------------

function bouncer (arrToFilter){

    return arrToFilter.filter(Boolean);
}

//----------Code without the filter method---------

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]));

Hope this helps to understand, the method, and the first thing that was not understanding was the part of passing the function, the predicate to the method, if I have mistakes here please suggest corrections.

Looks like Boolean is the simplest fix/answer for the "FreeCodeCamp" challenge, however it might be useful to try a couple of things just to get the hang of "why" and "how".

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

This evaluates everything passing through the filter, using the function(callback) passed in, which returns values. If it doesn't return a value, which null etc won't, it won't be included in the return. At least this method helped me understand why rather than just pass the test.

I slightly modified https://stackoverflow.com/a/35327425/3932895 to set everything to zero that has no numerical value

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

Tested with

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

in

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

results to

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

If you're using typescript, you can use the following gaurd function which both filters nulls and also narrows down the return type from (T | null)[] to string[]

function noNull<T>(value: T | null | undefined): value is NonNullable<T> {
  // Boolean constructore filters all NaN, null, undefined, zero and false
  return Boolean(value);
}

and use it like this:

const arr: (string | null)[] = ['d', null];
const result = arr.filter(noNull); //result type will be string[]

function bouncer(arr) {
  // Don't show a false ID to this bouncer.

  function isFalsyBouncer(value){
    if(Boolean(false)||Boolean(null)||Boolean(0)||Boolean("")||Boolean(undefined)||Boolean(NaN)){

    }else{
      return value;
    }
  }
  var filtered=arr.filter(isFalsyBouncer);
  return filtered;
}
发布评论

评论列表(0)

  1. 暂无评论