How to filter() out NaN, null, 0, false in an arra

2019-01-18 06:03发布

问题:

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

回答1:

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.



回答2:

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.



回答3:

You can also use an identity function instead of Boolean.

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


回答4:

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


回答5:

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.



回答6:

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;
}


回答7:

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


回答8:

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.



回答9:

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.



回答10:

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;
}