2

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

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Zack Xu
  • 11,505
  • 9
  • 70
  • 78
  • `filter(item => typeof item !== 'boolean')` – chovy Jun 24 '23 at 13:15
  • 1
    *JavaScript thinks that false is not a Number, but true is.* It does not, try adding `0` to your array. `.filter(Number)` is interpreted approx. as `x => !!Number(x)` (of course you shouldn't write such thing in your code): parse to `Number` and check if it's not 0 or NaN. – STerliakov Jun 24 '23 at 13:15
  • `[0,'0',1,'1'].filter(Number)` returns `[ 1, '1' ]`. Thanks for pointing this out. Guess I have to use the longhand – Zack Xu Jun 24 '23 at 13:19
  • 1
    `filter(x => x!==!!x)` – blakkwater Jun 24 '23 at 13:28
  • 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')` ... and `typeof` is an operator and not a function. I fixed that in the originally posted code. Of cause one could be more expressive by writing an `isNumber` function which implements a number validation. Then the code becomes even more expressive ... `[1, true, 2, false, 3].filter(isNumber)`. – Peter Seliger Jun 24 '23 at 14:52
  • @ZackXu ... Regarding all the so far provided answers, are there any questions left? – Peter Seliger Jul 24 '23 at 09:37

5 Answers5

0

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.

Pointy
  • 405,095
  • 59
  • 585
  • 614
0

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

... that pretty much is 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; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
-1

Try this:

const list = [1, true, 2, false, 3];
const newList = list.filter(item => Number.isInteger(item));

console.log({ newList });
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • `isNumber` is not defined – Bergi Jun 24 '23 at 17:14
  • Sorry for that, i fixed the code, hope this will work – Ghadeer Ahmad Jun 24 '23 at 17:23
  • Th parseInt function is used to convert string to integer and it gives NaN when it fails, you can use instead Number.isInteger to check if the item is number or not – Ghadeer Ahmad Jun 24 '23 at 19:15
  • Sorry i wrote parseInst instead of parseInt. My mistake – Ghadeer Ahmad Jun 24 '23 at 19:19
  • And yes i tested the code before i answer your question, but it is a typo error while writing the answer. – Ghadeer Ahmad Jun 24 '23 at 19:21
  • @GhadeerAhmad ... the [`radix` parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#parameters) is still missing. And why didn't you use the edit to change it to [`Number.isInteger`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger) as you already did mention yourself? – Peter Seliger Jun 24 '23 at 19:22
  • 1
    Here is the update. I edited it for you. – Ghadeer Ahmad Jun 24 '23 at 19:28
-1

typeof

let array = [true, false, true, 1, true, 2, false, 3];

var i = array.length
while (i--) {
  if (typeof array[i] === 'boolean') { 
      array.splice(i, 1);
  } 
}

console.log(array)
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
-2

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

Robert
  • 10,126
  • 19
  • 78
  • 130
  • @PeterSeliger it resolves the issue stated. In my answer I'm using the input provided by the OP. If more types of input need to be considered than the question can be updated. – Robert Jun 24 '23 at 15:27