Filtering an array by 'truthy' or 'falsy'

let array_rawData = ['red', '', 0, 42, 'blue', 42, -0, 
null, undefined, NaN, 'hike!', 0n];

let _rawArrayData_toBeTruthy = array_rawData;
let _rawArrayData_toBeFalsy = array_rawData;

function truthy_Check (_rawData) {
    if ((_rawData !== '') 
        && (_rawData !== 0) 
        && (_rawData !== -0) 
        && (_rawData !== null) 
        && (_rawData !== undefined)
        && (_rawData !== 0n) 
        && (_rawData !== NaN)) {
        return _rawData;
    } 
}

function falsy_Check (_rawData) {
    if ((_rawData === '') 
        || (_rawData === 0) 
        || (_rawData === -0) 
        || (_rawData === null) 
        || (_rawData === undefined)
        || (_rawData === 0n) 
        || (_rawData === NaN)) {
        return _rawData;
    } 
}

let array_filteredForTruthy = _rawArrayData_toBeTruthy.filter(truthy_Check);
let array_filteredForFalsy = _rawArrayData_toBeFalsy.filter(falsy_Check);


console.log(array_filteredForTruthy);
console.log(array_filteredForFalsy);



I don’t understand why array_filteredForTruthy is being filled correctly, but array_filteredForFalsy is empty. What am I missing here?

So I took this to StackOverflow and I learned some things:

  1. If I assign a new array to an old array, ex: let newArray = oldArray; then the newArray is only pointing towards the oldArray in memory, it isn’t actually making a clone of the old array. In my original code I made two new arrays under the assumption that I was making clones to manipulate the data without altering the original, but it turns out that wouldn’t have mattered. Note: this also applies to objects (and arrays are objects!).

  2. .filter() moves through an array item by item and looks for a Boolean to be returned based on the predicate criteria of my function truthyCheck. This means that in order to function correctly given my code, instead of returning the items, I should simply return true; or return false;. Additionally, .filter() itself creates a copy of the original array without altering it, meaning that when I assign arrayFilteredForTruthy = rawArrayData.filter(dataCheck), the new, filtered array points to the array made by the function, so I don’t need to split the original array into two like I did.

  3. a non-Boolean can be ‘coarsed’ into a Boolean using the !x and !!x. If I’m looking to return something that’s ‘falsy’, then I can use !falsyData to have this evaluate to true, and if I have a ‘truthy’ datum then I can also force it into a Boolean by making it evaluate in the negative twice, back to true.

  4. To clone an array (or an object??) in ES6, the easiest way is to use let cloneArray = […originalArray]; and in older version of ES, the syntax would be let cloneArray = originalArray.slice(); although I don’t know the exact usage of slice, so I’ll just use […x] for now.

  5. I can’t use === to test NaN, I’d have to use isNaN(), but it’s easier to simply use !x when I recode this exercise.

Hi,

Thanks for the post. I am glad you got it working. Here is an alternative way to implement this, that is similar to yours. I have also added some comments that hopefully make some sense to what is going on.

let array_rawData = ['red', '', 0, 42, 'blue', 42, -0, null, undefined, NaN, 'hike!', 0n];

// the two arrays below are pointing to the same array as array_rawData
let _rawArrayData_toBeTruthy = array_rawData;
let _rawArrayData_toBeFalsy = array_rawData;

function truthy_Check (_rawData) {
    return _rawData || false;
}

function falsy_Check (_rawData) {
        return !(_rawData);
    } 

/* 
  think about how you used accessed filter, you used dot notation. 
  Dot notation is used to access members (properties) of an object. 
  So when you used  _raw_ArrayData_toBeTruthy.filter, you were 
  accessing a method on that object named filter. The method 
  has access to other properties on the object, like the 
  arguments you passed into it when you created it using 
  the array literal notation []. It is looping through 
  those and passing each one to your call back function 
  named "falsy_Check" or "truthy_Check" and adding them to a 
  new array when the result is true. Then returning the new array. 

  function falsy_Check (_rawData) {
        return !(_rawData);
    } 

  function filter(falsy_Check) {
    let newArray = [];

    for (const item in this.array) {
        if (falsey_Check(item) {
            newArray.push(item);
        };
    }

    return newArray;
  }
 */

let array_filteredForTruthy = _rawArrayData_toBeTruthy.filter(truthy_Check);
let array_filteredForFalsy = _rawArrayData_toBeFalsy.filter(falsy_Check);


console.log(array_filteredForTruthy);
console.log(array_filteredForFalsy);

/* 
    Proves that the filtered arrays do not point back to array_rawData array, because the filter method
    created a new array within the function and then returned it.  
*/
console.log(array_filteredForTruthy === array_rawData);
console.log(array_filteredForFalsy === array_rawData);

JavaScript is a very unique language and that can make it hard to understand at first.

try this…

 let names = ['john doe', 'jane doe'];

/* 
    accessing array items through object bracket notation. 
    You shouldnt do this in working code, but this is for fun
*/
console.log(names['0']);
console.log(names['1']);

In the comments in the code above there is a example of how to implement the filter function, this.array is not actually what is used but I think it makes understanding the concept of what is happening a little easier.

Thanks