如何对包含 NaN 的 JavaScript 数组进行排序?

问题描述 投票:0回答:5

我正在尝试对有时具有

Infinity
NaN
的数组进行排序。当我使用标准 JavaScript
array.sort()
时,它似乎会进行排序,直到达到
NaN
,然后我会得到随机结果。

var array =[.02,.2,-.2,Nan,Infinity,20];

有没有办法仍然对其进行排序,以便最终结果从负到正,并且最后仍然有

NaN
Infinity

-.2,.02,.2,20,NaN,Infinity
javascript arrays sorting nan
5个回答
14
投票

负无穷大在逻辑上应该排在第一位,因为它实际上小于所有其他数字。

我会这样做:

const cmp = (a,b) => a-b || isNaN(a)-isNaN(b);

// Example
const arr = [Infinity, NaN, Infinity, -Infinity, NaN, 1, 0, NaN, -1, -0];
console.log(arr.sort(cmp));

这里 -0 和 0 被认为是相等的,并且可以以任何相对顺序出现。

如果你想确保 -0 在 0 之前排序,那么:

const cmp = (a,b) => a-b || isNaN(a)-isNaN(b) || Object.is(b, -0) - Object.is(a, -0);

// Example
const arr = [Infinity, NaN, Infinity, -Infinity, NaN, 1, 0, NaN, -1, -0];
console.log(arr.sort(cmp));

请注意,堆栈片段不会保留

-0
...请参阅浏览器控制台。


14
投票

如果您只想以随机顺序将它们放到最后:

var arr = [-1, 0, 1, 10, NaN, 2, NaN, 0, -1, NaN, 5, Infinity, 0, -Infinity];

arr.sort(function(a, b) {
  if (!isFinite(a) && !isFinite(b)) {
    return 0;
  }
  if (!isFinite(a)) {
    return 1;
  }
  if (!isFinite(b)) {
    return -1;
  }
  return a - b;
});

console.log(...arr)
//[-1, -1, 0, 0, 0, 1, 2, 5, 10, NaN, NaN, NaN, Infinity, -Infinity]

如果您还想在最后对无穷大进行排序:

var arr = [-1, 0, 1, 10, NaN, 2, NaN, 0, -1, NaN, 5, Infinity, 0, -Infinity];

arr.sort(function(a, b) {
  if( !isFinite(a) && !isFinite(b) ) {
    return ( isNaN(a) && isNaN(b) )
        ? 1
        : a < b
            ? -1
            : a === b
                ? 0
                : 1;
  }
  if( !isFinite(a) ) {
      return 1;
  }
  if( !isFinite(b) ) {
      return -1;
  }
  return a-b;
});

//[-1, -1, 0, 0, 0, 1, 2, 5, 10, -Infinity, Infinity, NaN, NaN, NaN]
console.log(...arr)

这里的顺序是

-Infinity
<
Infinity
<
NaN


12
投票

注意:此解决方案在某些边缘情况下存在问题,并且似乎不完全独立于浏览器,请参阅 Esailija 的答案或来自 trincot

的现代答案

对于这些情况,您可以使用 JavaScript 的内置实用函数捕获

NaN
Infinity

//sort -Infinity, NaN, Infinity to the end in random order
func = function(a,b){
  if(isFinite(a-b)) {
    return a-b; 
  } else {
    return isFinite(a) ? -1 : 1;
  }
};

//[-1,-1,0,0,1,2,5,6,10,NaN,Infinity,Infinity,NaN,-Infinity,NaN]
console.log(...[Infinity, -1, 6, 1, 0, NaN, 0, -1, 2, 5, 10, -Infinity, NaN, Infinity, NaN].sort(func))
// fails for edge case
console.log(...[-Number.MAX_VALUE, Number.MAX_VALUE].sort(func))
console.log(...[Number.MAX_VALUE, -Number.MAX_VALUE].sort(func))




//sort -Infinity<0<Infinity<NaN
func = function(a,b){
  if(isNaN(a)) { 
    return isNaN(b) ? 1 : b;
  } else {
    return isNaN(b) ? -1 : a-b; 
  }
}

//[-Infinity,-1,-1,0,0,1,2,5,6,10,Infinity,Infinity,NaN,NaN,NaN]
console.log(...[Infinity, -1, 6, 1, 0, NaN, 0, -1, 2, 5, 10, -Infinity, NaN, Infinity, NaN].sort(func))
console.log(...[-Number.MAX_VALUE, Number.MAX_VALUE].sort(func))
console.log(...[Number.MAX_VALUE, -Number.MAX_VALUE].sort(func))


0
投票

有这样的事吗?

var arr = [-1, 0, 1, 10, NaN, 2, NaN, 0, -1, NaN, 5, Infinity, 0];

function sortInf(a, b) {
  a = parseFloat(a);
  b = parseFloat(b);
  if ((!a || a === -Infinity) && a !== 0) {
    return 1;
  } else if ((!b || b === -Infinity) && b !== 0) {
    return -1;
  } else return a - b;
}
console.log(...arr.sort(sortInf));


-1
投票

一种简单快速的方法,没有条件或函数开销:

var r = [1, 9, NaN, 3, 4, 5, 0, -4, NaN, 4, Infinity, 7, 2];
r.sort(function(a, b, c) {return a - b || (a || Infinity) - (b || Infinity) || 0});
console.log(...r) // == -4,0,1,2,3,4,4,5,7,9,NaN,NaN,Infinity

编辑:根据反馈进行更新以避免 NaN 返回。

它的执行速度比其他答案快约 20 倍,因此如果您需要性能,那么它是理想的选择,并且排序是性能通常很重要的一个领域...

© www.soinside.com 2019 - 2024. All rights reserved.