如何正确地对整数数组进行排序

1388

尝试从一个我知道只包含整数的数组中获取最高和最低值似乎比我想象的更难。

var numArray = [140000, 104, 99];
numArray = numArray.sort();
console.log(numArray)

我希望它展示的是99, 104, 140000,但实际上它展示的是104, 140000, 99。因此看起来排序函数将这些值视为字符串。

有没有办法让排序函数按照整数值进行排序?


6
顺便说一下,如果你要排序大量的整数,最好使用类似于计数排序这样的整数排序算法。计数排序所需运行的时间与数组大小成线性关系:O(n)。而本文中提供的所有解决方案都使用比较排序,效率较低:O(n * log n)。 - Web_Designer
4
计数排序在考虑数字范围时是线性的,而不是考虑数组大小。例如,对于[1,1000000]进行排序需要超过2步,因为算法必须扫描1到1000000之间的每个数组索引,以查看哪个单元格的值大于0。 - yters
10
JS仍然存在这个bug,这相当疯狂。 - user894319twitter
6
@user894319twitter说:"这太不真实了,我真的只能称之为一个 bug。如果这在规范中,那么他们在规范中指定了一个 bug。这是一个 bug。" - gjvdkamp
2
我真的很想知道是什么思维过程导致了这个结论:“这是sort()的一个很好的实现”。 - Welcor
显示剩余5条评论
32个回答

13
问题已经有答案了,最短的方法是使用sort()方法。但如果你正在寻找更多对数组进行排序的方法,并且您也喜欢循环,请查看以下内容。
插入排序

Ascending:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] > target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

降序:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] < target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

选择排序:

升序:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] < numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

降序:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] > numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

玩得开心


这些算法是否比使用像此答案建议的TypedArray上的sort()更快呢?对于小数组,它们可能会更快,但对于中大型数组肯定不会更快,因为这些都是O(n^2)算法。 - Peter Cordes

12
在JavaScript中,sort()方法的默认行为是按字母顺序对数组中的值进行排序。
要按数字排序,您必须定义一个数字排序函数(非常容易):
...
function sortNumber(a, b)
{
  return a - b;
}

numArray = numArray.sort(sortNumber);

9

Array.prototype.sort()是对数组进行排序的常用方法,但是我们需要注意一些问题。

默认情况下,排序顺序是按字典顺序排序,而不是按数字顺序排序,无论数组中的值的类型是什么。即使数组全是数字,所有的值也将转换为字符串并按字典顺序排序。

因此,我们应该像下面这样自定义sort()和reverse()方法。

参考网址

如果要对数组内的数字进行排序

numArray.sort(function(a, b)
{
    return a - b;
});

对于反转数组中的数字

numArray.sort(function(a, b)
{
    return b - a;
});

Referred URL


8

下面的'numerically'函数通常用作回调函数,在许多情况下对数字数组进行数值排序:

function numerically(a, b){
    return a-b;
}

array.sort(numerically); 

但是,在某些罕见情况下,当数组包含非常大的负数时,由于a-b变得比JavaScript可以处理的最小数字还要小,因此可能会发生溢出错误。

因此,编写数值函数的更好方法如下:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}

1
JavaScript的数字是浮点数。IEEE754定义了溢出和下溢规则,包括溢出到+-Infinity,下溢到subnormal或+-0.0。即使两个数字都很大且相近,我认为它们的减法也不会下溢到+-0.0。两个双精度浮点数之间的差值总是可以表示为另一个非零双精度浮点数(除非它溢出,例如DBL_MIN-DBL_MAX),但下溢是不可能的。灾难性抵消使结果不精确,失去了大部分“有效数字”,但是**a-b始终是非零的,并具有a!=b的正确符号。** - Peter Cordes

6

处理undefined、null和NaN:null的行为类似于0,而NaN和undefined则排在最后。

array = [3, 5, -1, 1, NaN, 6, undefined, 2, null]
array.sort((a,b) => isNaN(a) || a-b)
// [-1, null, 1, 2, 3, 5, 6, NaN, undefined]

1
语言规范要求比较函数在对数组中的任意两个元素进行比较时,始终返回一个非NaN的数字。当b为NaN或undefined时,此函数返回NaN;当a和b都是Infinity或都是-Infinity时,也会返回NaN。 - Adam M. Costello
检查NaN的想法并不错,但是这段代码没有将NaN放到最后。 - Konstantin Smolyanin

5

接受的答案以及等价的方法,例如numArray.sort((a,b) => a - b)在数组中仅包含没有无穷大或NaN的数字时非常好。它们可以通过以下方式扩展以处理无穷大和NaN:

numArray.sort((a,b) => (+a || 0) - (+b || 0) || 0);

这将把NaN(或任何非数字,如'foo'或{})视为0进行排序。最后的|| 0是必需的,以处理a和b相等的无穷大情况。


4
虽然在JavaScript中不是必需的,但如果您希望sort()compareFunction严格返回-1、0或1(类似于PHP中的spaceship operator的工作方式),则可以使用Math.sign()。下面的compareFunction严格返回-1、0或1:
numArray.sort((a, b) => Math.sign(a - b));

注意: Math.sign()在Internet Explorer中不受支持。


3

对于普通的元素值数组:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
**output : [1, 2, 2, 24, 64, 545, 676]**

var array2 = ["v","a",545,676,64,2,"24"]
**output: ["a", "v", 2, "24", 64, 545, 676]**

对于一个对象数组:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

**output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]**

3
为了创建这种排序,你需要传递一个函数来检查哪个先出现。
在函数内定义要检查的值:a.id - a.id

        const myJson = [
            { id: 1, name: 'one'},
            { id: 4, name: 'four'},
            { id: 2, name: 'two'},
            { id: 3, name: 'three'}
        ];

        // provide the sort method to check
        const myNewSort = myJson.sort(function(a, b) {
          return a.id - b.id;
        });

        console.log('my new sort',myNewSort)


2

尝试使用以下代码

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接