Bagaimana cara mengurutkan array 2 dimensi berdasarkan nilai kolom?

90

Adakah yang bisa membantu saya mengurutkan Array 2 dimensi di JavaScript?

Ini akan memiliki data dalam format berikut:

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

Ini akan terlihat seperti ini ketika diurutkan:

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

Jadi intinya, mengurutkan berdasarkan kolom pertama.

Bersulang

Alex
sumber
3
Inilah semua yang perlu Anda ketahui: MDN - Array.sort ()
jahroy
1
tolong terima jawaban dari @PramodVemulapalli, semua yang saat ini memiliki suara terbanyak salah!
Bergi
@jahroy: Ini bukan tentang pemaksaan tipe, ini tentang persyaratan untuk fungsi perbandingan yang konsisten.
Bergi

Jawaban:

110

Sesederhana ini:

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

Saya mengundang Anda untuk membaca dokumentasi .

Jika Anda ingin mengurutkan berdasarkan kolom kedua, Anda dapat melakukan ini:

a.sort(compareSecondColumn);

function compareSecondColumn(a, b) {
    if (a[1] === b[1]) {
        return 0;
    }
    else {
        return (a[1] < b[1]) ? -1 : 1;
    }
}
jahroy
sumber
4
Harap benar-benar menguji kode Anda. jsfiddle.net/DuR4B/2 . Langsung dari tautan dokumentasi yang Anda posting: "Jika bandingkanFungsi tidak disediakan, elemen diurutkan dengan mengonversinya menjadi string dan membandingkan string dalam urutan leksikografik (" kamus "atau" buku telepon ", bukan numerik). Misalnya," 80 "muncul sebelum "9" dalam urutan leksikografik, tetapi dalam urutan numerik 9 muncul sebelum 80. "
Ian
3
@ Ian - Kamu benar. Poin yang bagus. Saya rasa saya terlalu bersemangat untuk membuktikan suatu hal tentang kesederhanaan. Saya sudah mengujinya, tetapi tidak sepenuhnya. Sekarang saya akan memperbaikinya ... Saya berharap data sampel telah membuktikan maksud Anda sebelum saya mengoleskan telur itu ke seluruh wajah saya!
jahroy
Haha aku tahu aku tahu, aku benci jika hal semacam itu terjadi. Kelihatannya benar tetapi ada sesuatu yang secara internal mengubahnya yang tidak berjalan seperti yang diharapkan. Mirip seperti membandingkan string dengan <atau >. Bagaimanapun, saya suka pembaruannya :)
Ian
1
@Ash - Tempat terbaik untuk melihat adalah dokumentasi. Saya suka dokumentasi Mozilla, jadi ketika saya memiliki pertanyaan tentang fungsi JS, saya selalu google "mdn {{function_name}} " . Dalam hal ini istilah penelusurannya adalah "mdn array.sort" yang membawa Anda ke sini .
jahroy
1
... seperti yang akan Anda lihat di dokumentasi, metode array.sort () menggunakan fungsi sebagai argumen, yang cukup umum di JavaScript. Metode array.sort () dirancang sedemikian rupa sehingga ia tahu apa yang harus dilakukan dengan fungsi yang diteruskan kepadanya: ia menggunakannya untuk membandingkan elemennya. Ini biola yang benar - benar payah yang saya buat untuk mencoba menunjukkan bagaimana Anda meneruskan fungsi sebagai referensi ... maaf itu sangat buruk.
jahroy
65

Pendekatan terbaik adalah menggunakan yang berikut ini, karena mungkin ada nilai berulang di kolom pertama.

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]
});
Pramod Vemulapalli
sumber
Ini adalah jawaban yang benar, ini mempertimbangkan kedua digit dalam bilangan tersebut. Terima kasih!
torehan
52

coba ini

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

Catatan: Jawaban asli menggunakan lebih besar dari (>) daripada minus (-) yang dirujuk oleh komentar sebagai salah.

PSR
sumber
8
8 suara positif untuk solusi yang salah? Saya tidak dapat mempercayai ini. Silakan, baca tentang fungsi perbandingan dan pahami kapan mereka perlu mengembalikan nilai negatif.
Bergi
6
Seperti yang dikatakan Bergi, ini bukanlah solusi yang tepat. Meskipun mungkin berhasil dalam banyak kasus, akan ada saat-saat di mana itu tidak berfungsi seperti yang diharapkan dan Anda dibiarkan menggaruk-garuk kepala (itu telah terjadi pada saya). Inti masalahnya adalah bahwa fungsi perbandingan dalam solusi ini hanya mengembalikan dua keadaan (benar / 1, salah / 0), tetapi harus mengembalikan tiga keadaan (nol, lebih besar dari nol, dan kurang dari nol).
thdoan
1
Tidak berhasil untuk saya. @jahroy adalah orang dengan jawaban yang benar
erdomester
Hanya catatan untuk mereka yang membaca komentar: Jawabannya telah dikoreksi 5 Jan. Itu benar sekarang (fungsi bandingkan mengembalikan tiga kemungkinan status).
marlar
@Bergi, terima kasih telah menunjukkan hal ini. (bagi saya, ini tidak berfungsi dengan baik di IE11) dan saya tidak dapat memahami (mengapa ini berfungsi di chrome) sampai saya melihat komentar Anda. Terima kasih!
Alex Nevsky
12

Menggunakan fungsi panah, dan mengurutkan berdasarkan bidang string kedua

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

Dinesh Rajan
sumber
10

Jika Anda seperti saya, Anda tidak akan ingin melalui perubahan setiap indeks setiap kali Anda ingin mengubah kolom yang Anda sortir.

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);
Charles Clayton
sumber
Saya baru saja melihat jawaban Anda, setelah menyusun jawaban sendiri dengan alasan yang sama persis - dengan sedikit perbedaan - saya sebenarnya mengembalikan fungsi untuk mengurutkan secara langsung.
olamotte
3

Tidak ada yang istimewa, hanya menghemat biaya yang diperlukan untuk mengembalikan nilai pada indeks tertentu dari sebuah array.

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"]]"
Vikas Gautam
sumber
Bagaimana jawaban ini berbeda dengan jawaban saya di sini ?
Charles Clayton
1
1. Anda menggunakan a[colIndex]lagi dan lagi tetapi saya menangkapnya di sini a = a[colIndex]. Lebih efisien. 2. Saya menggunakan rasa yang berbeda if, membuatnya lebih pendek. 3. Saya tidak kembali arrsebagai hasil dari sortByColfungsi yang berarti fungsi saya tidak dapat digunakan untuk membuat referensi lain. Semoga membantu!
Vikas Gautam
3

dalam satu baris:

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)
}
Jared
sumber
3

Jika Anda ingin mengurutkan berdasarkan kolom pertama (yang berisi nilai angka ), coba ini:

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

Jika Anda ingin mengurutkan berdasarkan kolom kedua (yang berisi nilai string ), coba ini:

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

PS untuk kasus kedua, Anda perlu membandingkan antara nilai ASCII mereka.

Semoga ini membantu.

Sabbir Ahmed
sumber
0

Karena kasus penggunaan saya melibatkan lusinan kolom, saya memperluas jawaban @ jahroy sedikit. (juga baru menyadari @ charles-clayton memiliki ide yang sama.)
Saya meneruskan parameter yang ingin saya sortir, dan fungsi sortir didefinisikan ulang dengan indeks yang diinginkan untuk perbandingan berlangsung.

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;
    }
  }
}
olamotte
sumber
0

Berdiri di atas bahu charles-clayton dan @ vikas-gautam, saya menambahkan uji string yang diperlukan jika kolom memiliki string seperti pada OP.

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

Tes isNaN(a-b)menentukan apakah string tidak dapat dipaksa menjadi angka. Jika bisa maka a-btes tersebut valid.

Perhatikan bahwa mengurutkan kolom jenis campuran akan selalu memberikan hasil yang menghibur karena pengujian persamaan yang ketat (a === b)akan selalu menghasilkan nilai salah. Lihat MDN di sini

Ini adalah skrip lengkap dengan pengujian Logger - menggunakan Skrip 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"],
                          ]"
*/

}
DeeKay789
sumber
Pembaruan kemungkinan bunga - 2 Juli 2019. Urutan sekarang 'stabil'. Baca disini. (via Mathias BynensVerified @mathias) v8.dev/features/stable-sort
DeeKay789