skip to Main Content

In JavaScript, I have an array containing boolean values and integer numbers, eg

[1, true, 2, false, 3]

I want to get an array with the boolean values removed. I tried

> [1, true, 2, false, 3].filter(Number)
[ 1, true, 2, 3 ]

Strangely, JavaScript thinks that false is not a Number, but true is. How so?

If my array contains strings, it works.

> [1, '', 2, 'foo', 3].filter(Number)
[ 1, 2, 3 ]

I know I can write the following, I was hoping for an easier way.

> [1, true, 2, false, 3].filter(x => typeof x === 'number')
[ 1, 2, 3 ]

What’s the easiest way to achieve what I want?

Thanks

3

Answers


  1. The .filter() method interprets the return value of the callback as boolean. If you use Number() as the filter callback, everything that evaluates to 0 or NaN will be excluded from the result.

    What you really want to do is check the type of each value, which you can do with typeof.

    Login or Signup to reply.
  2. In case of just targeting integer or even safe integer values one could do …

    [1, true, 2, false, 3].filter(Number.isInteger);
    

    … respectively …

    [1, true, 2, false, 3].filter(Number.isSafeInteger);
    

    … thats pretty much the easiest to go with.

    And from another of my above comments …

    The "easiest" way is also the one that expresses exactly what is going to be achieved. Thus, the very expressive / readable / comprehensible last variant presented by the OP is the one to go with … [1, true, 2, false, 3].filter(x => typeof x === 'number')

    … Of cause one could be more expressive by writing an isNumber function which implements a number validation. Then the code becomes even more expressive …

    function isNumber(value) {
      return Object
        .prototype
        .toString
        .call(value) === '[object Number]';
    }
    
    function isNumberValue(value) {
      return typeof value === 'number';
    }
    function isFiniteNumberValue(value) {
      return isNumberValue(value) && Number.isFinite(value);
    }
    const testData = [1, true, 2, '', 3, 0/0, new Number(1111)];
    
    console.log(
      'any number ...',
      testData.filter(isNumber)
    );
    console.log(
      'any number value ...',
      testData.filter(isNumberValue)
    );
    console.log(
      'any finite number value ...',
      testData.filter(isFiniteNumberValue)
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }
    Login or Signup to reply.
  3. Using the input provided in your question, try this:
    [1, true, 2, false, 3].filter(el => (el === 0 || parseInt(el)));
    Or try this simpler one [1, true, 2, false, 3].filter(Number.isInteger);

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search