Home > Software design >  Filter Method Behavior
Filter Method Behavior

Time:01-12

Why filter method can't work with ternary conditional as it works with if conditionals ?

In case it works with if..else

let numbers = [-1, -2, -3, 1, 2, 3];
let negatives = [];

let positives = numbers.filter(num => {
   if(num > 0) {
     return num;                      // positives array => [1, 2, 3]
   } else {
     negatives.push(num);             // negatives array => [-1, -2, -3]
   }
})

In case it works with ?

let positives = numbers.filter(num => num > 0 ? num : negatives.push(num));

// positives array => [-1, -2, -3, 1, 2, 3]

// negatives array => [-1, -2, -3]

I tried filter method with if conditionals and it returns the result as I expect. but what is not expected for me the result when it works with ternary conditional.

CodePudding user response:

The issue is that you are misunderstanding what the code you pasted does.

Let's see.. in the first code, the fitering function returns either num or nothing (after negatives.push() there is no return, so it implicitly returns undefined).

function fn(){ 
  // no explicit return
}
const what = fn();
typeof what === "undefined"; // true

The second version, returns either num or the returned value of negatives.push() call, which is by definition:

Return value

The new length property of the object upon which the method was called.

So in the second version of the code, the filter receives for every negative number: 0, 1, 2... and so on. The first occurrence will be taken as a "falsy" (0 is a "falsy" value in JS) so it will be filtered out from the resulting array, the following negative numbers will be included in the resulting array as the filtering function will return "truthy" values for them (positive numbers are "truthy" values in JS)


Being that said...

It is a bad practice to use a filter function for other task than filtering things. In this scenario where you need to separate positives from negatives, use forEach which is more clear and appropriate.

const positives = [];
const negatives = [];

numbers.forEach(num => {
   if(num > 0) { // Note: that this comparison will send ZEROES to negatives array, which could lead to a bug.
     positives.push(num);
   } else {
     negatives.push(num);
   }
}); 

or simpler:

const positives = [];
const negatives = [];

numbers.forEach(num => (num > 0 ? positives : negatives).push(num));

CodePudding user response:

The array method filter expects a callback which returns a boolean value. In your second example you are returning num when num is positive (which is truthy).

However, when num is negative, the method returns the result of negatives.push(num) which is also truthy.

CodePudding user response:

the filter method is not returning a correct boolean value. It is better to return exact boolean 'type' value.

let numbers = [-1, -2, -3, 1, 2, 3];
const negatives = [];

const positives = numbers.filter((num) => {
  if (num > 0) {
    return true;
  }
  negatives.push(num);
  return false;
});

console.log(negatives)
console.log(positives)

  • Related