比较运算符不适用于 JavaScript 中的 0

Comparison operator is not working on 0 in JavaScript

我一直在尝试回答我偶然发现 Codewars 的这个问题。

You are given an array (which will have a length of at least 3 but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N.

这是我最初的回答。

let array = [0, 1, 2];

function findOutlier(integers) {
  let evens = integers.filter(item => {
    if (item % 2 === 0 || item === 0) {
      return item;
    }
  });
  let odds = integers.filter(item => {
    if (item % 2 !== 0) {
      return item;
    }
  });
  if (evens.length > 1) {
    return odds[0];
  } else {
    return evens[0];
  }
}
console.log(findOutlier(array));

但显然 item === 0 在上面的代码中不起作用,它 returns [2]作为 evens 的值(漏掉 0)。 然后我像下面这样更改了代码并且它起作用了!

let array = [0, 1, 2];

function findOutlier(integers) {
  let evens = integers.filter(item => {
    if (item = 0 || item % 2 === 0) {
      return item;
    }
  });
  let odds = integers.filter(item => {
    if (item % 2 !== 0) {
      return item;
    }
  });
  if (evens.length > 1) {
    return odds[0];
  } else {
    return evens[0];
  }
}
console.log(findOutlier(array));

我仍然很困惑为什么比较运算符在第一个代码中不起作用。 如果您能帮助我理解,将不胜感激..!

filter 方法中,您需要 return truefalse,并且您正在 returning value。在第一种情况下,0 将根据您的代码得到 returned,并且 0 被视为 falsy 值。所以它不会显示在最终结果中。

let array = [0, 1, 2];

function findOutlier(integers) {
  let evens = integers.filter((item) => {
    if (item % 2 === 0) {
      return true;
    }
    return false;
  });

  console.log(evens);

  let odds = integers.filter((item) => {
    if (item % 2 !== 0) {
      return true;
    }
    return false;
  });

  console.log(odds);

  if (evens.length > 1) {
    return odds[0];
  } else {
    return evens[0];
  }
}
console.log(findOutlier(array));

您可以使此代码更多readable,如下面的片段所示

let array = [0, 1, 2];

function findOutlier(integers) {
  let evens = integers.filter(item => item % 2 === 0);
  let odds  = integers.filter(item => item % 2 !== 0);

  if (evens.length > 1) return odds[0];
  else return evens[0];
}

console.log(findOutlier(array));

问题就在这里

let evens = integers.filter(item => {
    if (item = 0 || item % 2 === 0) {
      return item; // You are return value instead of boolean
    }
});

应该是

let evens = integers.filter(item => {
    return item == 0 || item % 2 == 0; // It should be returned boolean
});

只是因为根据MDN's filter method说:

callback function is a predicate, to test each element of the array. Return a value that coerces to true to keep the element, or to false otherwise`.

let array = [0, 1, 2];

function findOutlier(integers){
    let evens = integers.filter(item => {
        return item == 0 || item % 2 == 0;
    });
    let odds = integers.filter(item => {
        return item % 2 !== 0;
    });
    
    if(evens.length > 1) {
        return odds[0];
    } else {
        return evens[0];
    }
}
console.log(findOutlier(array));

优化性能

function findOutlier(integers){
   const result = integers.reduce((acc, curr) => {
      if(curr % 2 === 0)
        acc["evens"].push(curr);
      else
        acc["odds"].push(curr);
      return acc;
    }, { evens: [],  odds: []});
    
   return result["evens"].length > 1 ? result["odds"][0] : result["evens"][0];
}
console.log(findOutlier([0, 1, 2]));

.filter() 方法接收一个谓词,该谓词必须 return 布尔值,truefalse,而不是 item。这是第一个错误。第二个是在 if 条件下使用赋值 =。单等号不代表比较。

要解决此问题,您可以在第一个代码示例中将 return item 替换为 return true。但是,我建议您使用简单的循环。

function findOutlier(integers) {
  for (let item of integers) {
    if (item % 2 != 0) {
      return item;
    }
  }
  return integers[0];
}