如何按列值对二维数组排序?


90

谁能帮我用JavaScript排序二维数组?

它将具有以下格式的数据:

[12, AAA]
[58, BBB]
[28, CCC]
[18, DDD]

排序时应如下所示:

[12, AAA]
[18, DDD]
[28, CCC]
[58, BBB]

因此,基本上,按第一列排序。

干杯


3
这是您需要了解的所有信息:MDN-Array.sort()
jahroy 2013年

1
请接受@PramodVemulapalli的回答,所有目前投票最多的人都是错误的!
Bergi 2014年

@jahroy:与类型强制无关,与一致比较功能的要求有关。
Bergi 2014年

Answers:


110

就这么简单:

var a = [[12, 'AAA'], [58, 'BBB'], [28, 'CCC'],[18, 'DDD']];

a.sort(sortFunction);

function sortFunction(a, b) {
    if (a[0] === b[0]) {
        return 0;
    }
    else {
        return (a[0] < b[0]) ? -1 : 1;
    }
}

我邀请您阅读文档

如果要按第二列排序,可以执行以下操作:

a.sort(compareSecondColumn);

function compareSecondColumn(a, b) {
    if (a[1] === b[1]) {
        return 0;
    }
    else {
        return (a[1] < b[1]) ? -1 : 1;
    }
}

4
请实际测试您的代码。jsfiddle.net/DuR4B/2。直接从您发布的文档链接中获取信息:“如果未提供compareFunction,则通过将元素转换为字符串并按字典顺序(“字典”或“电话簿”,而非数字)顺序比较字符串来对元素进行排序。例如,出现“ 80”按字典顺序在“ 9”之前,但按数字排序9在80之前。”
2013年

3
@Ian-你是对的。好点子。我想我很兴奋地证明了关于简单性的观点。我确实进行了测试,但是还没有完全测试。现在,我要修复它...我希望样本数据能证明您的观点,然后再将鸡蛋涂抹在脸上!
jahroy

哈哈,我知道我知道,我讨厌这种事情发生。看起来很正确,但是内部发生了一些变化,但未达到预期效果。Kinda喜欢将字符串与<或进行比较>。无论如何,我喜欢更新:)
2013年

1
@Ash-最好看的地方是文档。我喜欢Mozilla的文档,所以当我对JS函数有疑问时,我总是在Google上搜索“ mdn {{function_name}}。 ”在这种情况下,搜索词为“ mdn array.sort”,这将带您到这里
jahroy 2015年

1
...正如您将在文档中看到的那样,array.sort()方法将一个函数作为参数,这在JavaScript中非常普遍。该中的Array.sort()方法的设计,它知道如何处理传递给它的功能做的方式:它使用它来比较它的元素。这是我所做的一个非常la脚的小提琴,试图演示如何将函数作为引用进行传递...很抱歉。
jahroy 2015年

65

最好的方法是使用以下内容,因为第一栏中可能有重复的值。

var arr = [[12, 'AAA'], [12, 'BBB'], [12, 'CCC'],[28, 'DDD'], [18, 'CCC'],[12, 'DDD'],[18, 'CCC'],[28, 'DDD'],[28, 'DDD'],[58, 'BBB'],[68, 'BBB'],[78, 'BBB']];

arr.sort(function(a,b) {
    return a[0]-b[0]
});

这是正确的答案,它考虑了数字中的两个数字。谢谢!
尼克

52

试试这个

//WITH FIRST COLUMN
arr = arr.sort(function(a,b) {
    return a[0] - b[0];
});


//WITH SECOND COLUMN
arr = arr.sort(function(a,b) {
    return a[1] - b[1];
});

注意:原始答案使用的是大于(>)而不是减号(-),这就是注释所指的错误。


8
8票赞成公然错误的解决方案?我无法相信这。请阅读比较函数,并了解何时需要返回负值。
Bergi 2014年

6
正如Bergi所说,这不是正确的解决方案。尽管在许多情况下它可能会起作用,但有时它还是无法按预期起作用,并且您被抓挠了(这发生在我身上)。问题的症结在于,此解决方案中的比较函数仅返回两个状态(true / 1,false / 0),但应返回三个状态(零,大于零和小于零)。
thdoan'5

1
没有为我工作。@jahroy是正确答案的人
erdomester

只是为那些阅读注释的人提供的注释:答案已于1月5日得到纠正。现在是正确的(比较函数返回三种可能的状态)。
marlar

@Bergi,感谢您指出这一点。(对我来说,它在IE11中无法正常工作),直到我看到您的评论,我才能理解(为什么它在chrome中可以正常工作)。谢谢!
Alex Nevsky

12

使用箭头功能,并按第二个字符串字段排序

var a = [[12, 'CCC'], [58, 'AAA'], [57, 'DDD'], [28, 'CCC'],[18, 'BBB']];
a.sort((a, b) => a[1].localeCompare(b[1]));
console.log(a)


10

如果您像我一样,就不想在每次更改排序依据时都需要更改每个索引。

function sortByColumn(a, colIndex){

    a.sort(sortFunction);

    function sortFunction(a, b) {
        if (a[colIndex] === b[colIndex]) {
            return 0;
        }
        else {
            return (a[colIndex] < b[colIndex]) ? -1 : 1;
        }
    }

    return a;
}

var sorted_a = sortByColumn(a, 2);

在用完全相同的理由自己草拟了一个答案之后,我只是看到了您的答案-差别很小-我实际上返回了直接排序的函数。
olamotte

3

没什么特别的,只是节省了从数组中返回某个索引处的值所花费的成本。

function sortByCol(arr, colIndex){
    arr.sort(sortFunction)
    function sortFunction(a, b) {
        a = a[colIndex]
        b = b[colIndex]
        return (a === b) ? 0 : (a < b) ? -1 : 1
    }
}
// Usage
var a = [[12, 'AAA'], [58, 'BBB'], [28, 'CCC'],[18, 'DDD']]
sortByCol(a, 0)
console.log(JSON.stringify(a))
// "[[12,"AAA"],[18,"DDD"],[28,"CCC"],[58,"BBB"]]"

这个答案和我这里的有什么不同?
查尔斯·克莱顿

1
1.您a[colIndex]一次又一次地使用,但是我在这里捉住了它a = a[colIndex]。效率更高。2.我使用的口味不同if,使其更短。3.函数返回arr的结果不是我返回的,sortByCol这意味着我的函数无法用于创建另一个引用。希望能帮助到你!
Vikas Gautam'2

3

一行:

var cars = [
  {type:"Volvo", year:2016},
  {type:"Saab", year:2001},
  {type:"BMW", year:2010}
]


function myFunction() {
  return cars.sort((a, b)=> a.year - b.year)
}

3

如果要基于第一列(包含数字值)进行排序,请尝试以下操作:

arr.sort(function(a,b){
  return a[0]-b[0]
})

如果要基于第二列(包含字符串值)进行排序,请尝试以下操作:

arr.sort(function(a,b){
  return a[1].charCodeAt(0)-b[1].charCodeAt(0)
})

对于第二种情况,PS,您需要在它们的ASCII值之间进行比较。

希望这可以帮助。


0

由于我的用例涉及数十列,因此我扩展了@jahroy的答案。(也才意识到@ charles-clayton有相同的想法。)
我传递了要排序的参数,并使用所需的索引重新定义了sort函数,以进行比较。

var ID_COLUMN=0
var URL_COLUMN=1

findings.sort(compareByColumnIndex(URL_COLUMN))

function compareByColumnIndex(index) {
  return function(a,b){
    if (a[index] === b[index]) {
        return 0;
    }
    else {
        return (a[index] < b[index]) ? -1 : 1;
    }
  }
}

0

站在charles-clayton和@ vikas-gautam的肩膀上,我添加了字符串测试,如果一列具有OP中的字符串,则需要进行字符串测试。

return isNaN(a-b) ? (a === b) ? 0 : (a < b) ? -1 : 1 : a-b  ;

该测试isNaN(a-b)确定字符串是否不能强制为数字。如果他们可以,则a-b测试有效。

请注意,对混合类型的列进行排序将始终提供有趣的结果,因为严格相等性测试(a === b)将始终返回false。 在此处查看MDN

这是Logger测试的完整脚本-使用Google Apps脚本。

function testSort(){

function sortByCol(arr, colIndex){
    arr.sort(sortFunction);
    function sortFunction(a, b) {
        a = a[colIndex];
        b = b[colIndex];
       return isNaN(a-b) ? (a === b) ? 0 : (a < b) ? -1 : 1 : a-b  ;  // test if text string - ie cannot be coerced to numbers.
       // Note that sorting a column of mixed types will always give an entertaining result as the strict equality test will always return false
       // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

       }
}
// Usage
var a = [ [12,'12', 'AAA'],
          [12,'11', 'AAB'],
          [58,'120', 'CCC'],
          [28,'08', 'BBB'],
          [18,'80', 'DDD'],
        ]
    var arr1 = a.map(function (i){return i;}).sort();  // use map to ensure tests are not corrupted by a sort in-place.

    Logger.log("Original unsorted:\n     " + JSON.stringify(a));
    Logger.log("Vanilla sort:\n     " + JSON.stringify(arr1));
    sortByCol(a, 0);
    Logger.log("By col 0:\n     " + JSON.stringify(a));
    sortByCol(a, 1);
    Logger.log("By col 1:\n     " + JSON.stringify(a));
    sortByCol(a, 2);
    Logger.log("By col 2:\n     " + JSON.stringify(a));

/* vanilla sort returns " [
                            [12,"11","AAB"],
                            [12,"12","AAA"],
                            [18,"80","DDD"],
                            [28,"08","BBB"],
                            [58,"120","CCC"]
                          ]
   if col 0 then returns "[
                            [12,'12',"AAA"],
                            [12,'11', 'AAB'],
                            [18,'80',"DDD"],
                            [28,'08',"BBB"],
                            [58,'120',"CCC"]
                          ]"
   if col 1 then returns "[
                            [28,'08',"BBB"],
                            [12,'11', 'AAB'],
                            [12,'12',"AAA"],
                            [18,'80',"DDD"],
                            [58,'120',"CCC"],

                          ]"
   if col 2 then returns "[
                            [12,'12',"AAA"],
                            [12,'11', 'AAB'],
                            [28,'08',"BBB"],
                            [58,'120',"CCC"],
                            [18,'80',"DDD"],
                          ]"
*/

}

更新可能的利息-2019年7月2日。排序现在“稳定”。在这里阅读。(通过Mathias BynensVerified @mathias)v8.dev/features/stable-sort
DeeKay789 '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.