Làm thế nào để sắp xếp mảng 2 chiều theo giá trị cột?


90

Bất kỳ ai có thể giúp tôi sắp xếp một Mảng 2 chiều trong JavaScript không?

Nó sẽ có dữ liệu ở định dạng sau:

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

Nó sẽ trông như thế này khi được sắp xếp:

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

Vì vậy, về cơ bản, sắp xếp theo cột đầu tiên.

Chúc mừng


3
Mọi thứ đều ở đây bạn cần biết: MDN - Array.sort ()
jahroy

1
vui lòng chấp nhận câu trả lời của @PramodVemulapalli, tất cả những người hiện đang được bình chọn cao đều sai!
Bergi

@jahroy: Không phải là về kiểu ép buộc, mà là về các yêu cầu đối với các hàm so sánh nhất quán.
Bergi

Câu trả lời:


110

Thật đơn giản:

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

Tôi mời bạn đọc tài liệu .

Nếu bạn muốn sắp xếp theo cột thứ hai, bạn có thể làm như sau:

a.sort(compareSecondColumn);

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

4
Hãy thực sự kiểm tra mã của bạn. jsfiddle.net/DuR4B/2 . Ngay từ liên kết tài liệu bạn đã đăng: "Nếu CompareFunction không được cung cấp, các phần tử được sắp xếp bằng cách chuyển đổi chúng thành chuỗi và so sánh các chuỗi theo thứ tự từ vựng (" từ điển "hoặc" danh bạ ", không phải số). Ví dụ:" 80 "đi kèm trước "9" theo thứ tự từ vựng, nhưng theo thứ tự số 9 đứng trước 80 ".
Ian

3
@Ian - Bạn nói đúng. Điểm tốt. Tôi đoán rằng tôi đã quá phấn khích khi chứng minh một quan điểm về sự đơn giản. Tôi đã thử nghiệm nó, nhưng không hoàn toàn. Bây giờ tôi sẽ sửa nó ... Tôi ước dữ liệu mẫu đã chứng minh quan điểm của bạn trước khi tôi bôi quả trứng đó lên khắp mặt mình!
jahroy

Haha tôi biết tôi biết, tôi ghét khi những điều đó xảy ra. Có vẻ đúng như vậy nhưng có điều gì đó bên trong thay đổi nó không hoạt động như mong đợi. Kinda như so sánh các chuỗi với <hoặc >. Dù sao, tôi thích bản cập nhật :)
Ian

1
@Ash - Nơi tốt nhất để xem là tài liệu. Tôi thích tài liệu của Mozilla, vì vậy khi tôi có câu hỏi về một hàm JS, tôi luôn google "mdn {{function_name}} " . Trong trường hợp này, cụm từ tìm kiếm sẽ là "mdn array.sort". Điều này sẽ đưa bạn đến đây .
jahroy

1
... như bạn sẽ thấy trong tài liệu, phương thức array.sort () nhận một hàm làm đối số, điều này khá phổ biến trong JavaScript. Phương thức array.sort () được thiết kế theo cách mà nó biết phải làm gì với hàm được truyền cho nó: nó sử dụng nó để so sánh các phần tử của nó. Đây là một trò chơi thực sự khập khiễng mà tôi đã thực hiện để cố gắng chứng minh cách bạn chuyển các hàm làm tham chiếu ... xin lỗi, nó quá tệ.
jahroy

65

Cách tiếp cận tốt nhất là sử dụng cách sau, vì có thể có các giá trị lặp lại trong cột đầu tiên.

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

Đây là câu trả lời đúng, nó có tính đến cả hai chữ số trong số. Cảm ơn!
nick

52

thử đi

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

Lưu ý: Câu trả lời ban đầu sử dụng dấu lớn hơn (>) thay vì dấu trừ (-), điều mà các ý kiến ​​đề cập là không chính xác.


8
8 ủng hộ cho một giải pháp sai lầm trắng trợn? Tôi không thể tin điều này. Vui lòng đọc về các hàm so sánh và hiểu khi nào chúng cần trả về giá trị âm.
Bergi

6
Như Bergi đã tuyên bố, đây không phải là giải pháp đúng đắn. Mặc dù nó có thể hoạt động trong nhiều trường hợp, nhưng sẽ có lúc nó không hoạt động như mong đợi và bạn phải vò đầu bứt tai (điều đó đã xảy ra với tôi). Điểm mấu chốt của vấn đề là hàm so sánh trong giải pháp này chỉ trả về hai trạng thái (true / 1, false / 0), nhưng nó phải trả về ba trạng thái (0, lớn hơn 0 và nhỏ hơn 0).
thdoan

1
Không làm việc cho tôi. @jahroy là người đàn ông với câu trả lời đúng
erdomester

Chỉ là một lưu ý cho những người đọc các bình luận: Câu trả lời đã được sửa vào ngày 5 tháng 1. Hiện tại nó chính xác (hàm so sánh trả về ba trạng thái có thể có).
marlar

@Bergi, cảm ơn bạn đã chỉ ra điều này. (đối với tôi, nó không hoạt động bình thường trong IE11) và tôi không thể hiểu (tại sao nó hoạt động trong chrome) cho đến khi tôi thấy nhận xét của bạn. Cảm ơn!
Alex Nevsky

12

Sử dụng hàm mũi tên và sắp xếp theo trường chuỗi thứ hai

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

Nếu bạn giống tôi, bạn sẽ không muốn thực hiện thay đổi từng chỉ mục mỗi khi bạn muốn thay đổi cột mà bạn đang sắp xếp.

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

Tôi vừa thấy câu trả lời của bạn, sau khi tự mình soạn thảo một câu trả lời với cùng một suy luận chính xác - với một sự khác biệt nhỏ - tôi thực sự trả về hàm sắp xếp trực tiếp.
olamotte

3

Không có gì đặc biệt, chỉ tiết kiệm chi phí cần thiết để trả về một giá trị ở chỉ mục nhất định từ một mảng.

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"]]"

Câu trả lời này khác với câu trả lời của tôi ở đây như thế nào?
Charles Clayton

1
1. bạn đang sử dụng a[colIndex]một lần nữa và một lần nữa nhưng tôi đang bắt nó ở đây a = a[colIndex]. Nó hiệu quả hơn. 2. Tôi đang sử dụng hương vị khác của if, làm cho nó ngắn hơn. 3. Tôi không trả về arrlà kết quả của sortByColhàm có nghĩa là không thể sử dụng hàm của tôi để tạo một tham chiếu khác. Hy vọng nó giúp!
Vikas Gautam

3

trong một dòng:

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

Nếu bạn muốn sắp xếp dựa trên cột đầu tiên (chứa giá trị số ), hãy thử cách này:

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

Nếu bạn muốn sắp xếp dựa trên cột thứ hai (chứa giá trị chuỗi ), hãy thử cách này:

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

PS cho trường hợp thứ hai, bạn cần so sánh giữa các giá trị ASCII của chúng.

Hi vọng điêu nay co ich.


0

Vì usecase của tôi liên quan đến hàng chục cột, tôi đã mở rộng câu trả lời của @ jahroy một chút. (cũng vừa nhận ra @ charles-clayton cũng có ý tưởng tương tự.)
Tôi chuyển tham số mà tôi muốn sắp xếp theo và hàm sắp xếp được xác định lại với chỉ mục mong muốn để quá trình so sánh diễn ra.

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

Đứng trên vai của charles-clayton và @ vikas-gautam, tôi đã thêm kiểm tra chuỗi cần thiết nếu một cột có chuỗi như trong OP.

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

Kiểm tra isNaN(a-b)xác định xem các chuỗi không thể bị ép buộc thành số hay không. Nếu họ có thể thì a-bbài kiểm tra là hợp lệ.

Lưu ý rằng việc sắp xếp một cột có nhiều loại hỗn hợp sẽ luôn cho kết quả thú vị vì phép thử bình đẳng nghiêm ngặt (a === b)sẽ luôn trả về false. Xem MDN tại đây

Đây là tập lệnh đầy đủ với kiểm tra Trình ghi - sử dụng Google Apps Script.

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"],
                          ]"
*/

}

Cập nhật lãi suất có thể có - ngày 2 tháng 7 năm 2019. Sắp xếp hiện 'ổn định'. Đọc ở đây. (thông qua Mathias BynensVerified @mathias) v8.dev/features/stable-sort
DeeKay789 07/07/19
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.