【问题标题】:JavaScript: How do you sort an array that includes NaN'sJavaScript:如何对包含 NaN 的数组进行排序
【发布时间】:2013-07-07 15:00:24
【问题描述】:

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

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

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

-.2,.02,.2,20,NaN,Infinity

【问题讨论】:

  • 你能给我们举个数组的例子吗?
  • 调整函数中的逻辑来处理 NaN 的特殊情况会起作用吗?某种 if(isNaN(a)) { return positive } // 所以它总是在一端
  • @loosebazooka 的评论是问题的答案
  • 糟糕,我忘记了一个数字排序...修正了答案。
  • @loosebazooka,但为了排序,NaN 应该等于 NaN(即使在 JS 中是 NaN !== NaN

标签: javascript arrays sorting nan


【解决方案1】:

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

因此我会这样做:

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

【讨论】:

  • 这是最好的现代方法答案,它也解决了我在 Fabian 的答案中遇到的 chrome 问题。
【解决方案2】:

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

let array = [Infinity, -1, 6, 1, 0, NaN, 0, -1, 2, 5, 10, -Infinity, NaN, Infinity, NaN]



//sort -Infinity, NaN, Infinity to the end in random order
array.sort(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(array);



//sort -Infinity<0<Infinity<NaN
array.sort(function(a,b){
  if(isNaN(a)) { 
    return 1-isNaN(b);
  } else {
    return a-b; 
  }
});

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

【讨论】:

  • 末尾的括号缺失。似乎现在适用于我的测试用例。
  • 它本质上仍然是对数组进行洗牌。此外,isFinite 已经检查了 NaN
  • 当它明显被破坏时,很难理解它如何被接受为答案。 jsfiddle -> [2, NaN, -1, 0, 0, 0, 1, -1, 5, 10, -Infinity, NaN, NaN, Infinity]
  • 你的 jsfiddle jsfiddle.net/T6Lj8/1 给出的结果是 -1,-1,0,0,0,1,2,5,10,NaN,NaN,NaN,Infinity,-Infinity 问题出在哪里? (用 Firefox 和 Opera 测试)啊,用 Chrome 失败... -.-
  • @Xotic750 为了让它更加混乱,V8/Chrome/Chromium 对具有
【解决方案3】:

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

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;
});
//[-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]

这里的顺序是-Infinity Infinity NaN

【讨论】:

  • 不需要所有else ifs,否则+1
  • @Xotic750 怎么不需要 else ifs?
  • 因为return如果匹配。
  • @Xotic750 很好,现在删除它们
【解决方案4】:

这样的?

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;
}
alert(arr.sort(sortInf));

【讨论】:

  • 不适用于[-1, 0, 1, 10, NaN, 2, NaN, 0, -1, NaN, 5, Infinity, 0, -Infinity]
  • @Esailija 感谢您的信息,我只是没有使用所有可能的组合对其进行测试,修复了代码...
  • 在我看来仍然没有排序jsfiddl -> [-1, -1, 0, 0, 0, 1, 2, 5, 10, Infinity, NaN, -Infinity, NaN, NaN]
  • @Xotic750 OP 说“NaN or Infinities at the end”,我理解 Infinities 和 NaN 的顺序无关紧要,只是它们出现在数组的末尾。如果我错了,请纠正我...
  • 当然可以采用这种方式,因为 OP 不清楚,尽管 sort 对我来说意味着特定的排序,我不希望看到 Infinity, NaN, -Infinity, NaN。虽然 OP 的最新更新显示 -.2,.02,.2,20,NaN,Infinity
【解决方案5】:

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

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 });
 alert(r) // == -4,0,1,2,3,4,4,5,7,9,NaN,NaN,Infinity

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

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

【讨论】:

  • 这会将NaNs 返回到排序实现
  • @Esailija:为什么这么糟糕?你能详细说明一下吗? (它似乎对我有用)
  • 这里发生了什么? jsfiddle -> -Infinity, -1, -1, 0, 0, 0, 1, 2, 5, 10, NaN, NaN, NaN, Infinity]
  • 我没有看到 20X 的任何备份,例如在这里它实际上在 firefox jsperf.com/arrsarrs 中较慢。如果您需要对事物进行大量排序以担心性能,我实际上建议您使用不同的数据结构,例如二叉搜索树。
  • 即使删除了-Infinityjsfidde 仍然无法正常工作 - > [-1, -1, NaN, 0, NaN, 0, 0, 1, 2, 5, 10, Infinity, NaN]
猜你喜欢
  • 2011-07-04
  • 1970-01-01
  • 2020-11-02
  • 2015-04-06
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多