2 boyutlu diziyi sütun değerine göre nasıl sıralayabilirim?


90

Herhangi biri JavaScript'te 2 boyutlu bir Diziyi sıralamama yardımcı olabilir mi?

Verileri aşağıdaki formatta olacaktır:

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

Sıralandığında şöyle görünmelidir:

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

Yani temel olarak, ilk sütuna göre sıralama.

Şerefe


3
Bilmeniz gereken İşte her şey demek: MDN - Array.sort ()
jahroy

1
Lütfen @PramodVemulapalli'nin yanıtını kabul edin, şu anda yüksek oy alanların tümü yanlış!
Bergi

@jahroy: Bu tür zorlamasıyla ilgili değil, tutarlı karşılaştırma işlevleri için gereksinimlerle ilgili.
Bergi

Yanıtlar:


113

Bu kadar basit:

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

Sizi belgeleri okumaya davet ediyorum .

İkinci sütuna göre sıralamak isterseniz, bunu yapabilirsiniz:

a.sort(compareSecondColumn);

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

4
Lütfen kodunuzu gerçekten test edin. jsfiddle.net/DuR4B/2 . Doğrudan gönderdiğiniz belge bağlantısından: "CompareFunction sağlanmadıysa, öğeler dizelere dönüştürülerek ve dizgeleri sözlükbilimsel (" sözlük "veya" telefon rehberi "sayısal değil) karşılaştırılarak sıralanır. Örneğin," 80 "gelir sözlük sırasına göre "9" dan önce, ancak sayısal sıralamada 9, 80'den önce gelir. "
Ian

3
@Ian - Haklısın. İyi bir nokta. Sanırım basitlikle ilgili bir noktayı kanıtlamak için çok heyecanlandım. Test ettim ama tamamen değil. Şimdi düzelteceğim ... Keşke o yumurtayı yüzümün her tarafına sürmeden önce örnek veriler amacınızı kanıtlasaydı!
jahroy

Haha biliyorum biliyorum, bu tür şeylerden nefret ediyorum. Çok doğru görünüyor ama dahili olarak onu değiştiren ve beklendiği gibi yapmayan bir şey. Dizeleri <veya ile karşılaştırmak gibi >. Her neyse, ben güncelleme :) gibi
Ian

1
@ Ash - Bakılacak en iyi yer belgelerdir. Mozilla'nın belgelerini seviyorum, bu yüzden bir JS işlevi hakkında bir sorum olduğunda her zaman "mdn {{function_name}} " google'lıyorum . Bu durumda arama terimi "mdn array.sort" olacaktır ve sizi buraya getirir .
jahroy

1
... belgelerde göreceğiniz gibi, dizi.sort () yöntemi, JavaScript'te oldukça yaygın olan bir işlevi bağımsız değişken olarak alır. Array.sort () yöntemi kendisine geçirilen fonksiyonu ile ne yapacağını bilir bir şekilde tasarlanmıştır: kendi elemanlarını karşılaştırmak için kullanır. İşte fonksiyonları referans olarak nasıl geçirdiğinizi göstermek için yaptığım gerçekten kötü bir keman ... üzgünüm çok kötü.
jahroy

66

İlk sütunda tekrar eden değerler olabileceğinden, en iyi yaklaşım aşağıdakileri kullanmak olacaktır.

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

Bu doğru cevap, numaradaki her iki rakamı da dikkate alıyor. Teşekkürler!
ID

53

bunu dene

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

Not: Orijinal yanıtta eksi (-) yerine büyüktür (>) kullanılmıştır, bu da yorumların yanlış olarak bahsettiği durumdur.


8
Açıkça yanlış bir çözüm için 8 olumlu oy? Buna inanamıyorum. Lütfen karşılaştırma işlevlerini okuyun ve ne zaman negatif değerler döndürmeleri gerektiğini anlayın.
Bergi

6
Bergi'nin belirttiği gibi, bu doğru çözüm değil. Çoğu durumda işe yarasa da, beklendiği gibi çalışmayacağı ve başınızı kaşıyacağınız zamanlar olacaktır (benim başıma geldi). Problemin özü, bu çözümdeki karşılaştırma fonksiyonunun yalnızca iki durum (doğru / 1, yanlış / 0) döndürmesidir, ancak üç durum (sıfır, sıfırdan büyük ve sıfırdan küçük) döndürmelidir.
thdoan

1
Benim için çalışmadı. @jahroy doğru cevabı veren adam
erdomester

Yorumları okuyanlar için sadece bir not: Cevap 5 Ocak'ta düzeltildi. Şimdi doğru (karşılaştırma işlevi üç olası durum döndürür).
marlar

@Bergi, bunu işaret ettiğin için teşekkürler. (benim için, IE11'de düzgün çalışmıyor) ve yorumunuzu görene kadar (neden Chrome'da çalıştığını) anlayamadım. Teşekkürler!
Alex Nevsky

12

Ok işlevini kullanma ve ikinci dize alanına göre sıralama

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

Benim gibiyseniz, sıraladığınız sütunu her değiştirmek istediğinizde her bir dizini değiştirmek istemezsiniz.

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

Cevabınızı az önce gördüm, aynı mantıkla kendi kendime bir cevap hazırladıktan sonra - küçük bir farkla - aslında doğrudan sıralamak için işlevi döndürüyorum.
olamotte

3

Özel bir şey yok, sadece bir diziden belirli bir indekste bir değer döndürmek için gereken maliyeti düşürmek.

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

Bu yanıt benim buradaki yanıtımdan nasıl farklı ?
Charles Clayton

1
1. a[colIndex]tekrar tekrar kullanıyorsun ama burada yakalıyorum a = a[colIndex]. Daha verimli. 2. Farklı tatları kullanıyorum if, daha kısa hale getiriyorum. 3. İşlevin arrbir sonucu olarak geri dönmüyorum , sortByColbu da işlevimin başka bir referans oluşturmak için kullanılamayacağı anlamına geliyor. Umarım yardımcı olur!
Vikas Gautam

3

tek satırda:

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

Birinci sütuna ( sayı değerini içeren ) göre sıralamak istiyorsanız , şunu deneyin:

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

İkinci sütuna ( dize değerini içeren ) göre sıralamak istiyorsanız , şunu deneyin:

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

İkinci durum için PS, ASCII değerleri arasında karşılaştırma yapmanız gerekir.

Bu yardımcı olur umarım.


0

Kullanım durumum düzinelerce sütun içerdiğinden, @ jahroy'un yanıtını biraz genişlettim. (@ charles-clayton da aynı fikre sahipti.)
Sıralamak istediğim parametreyi geçtim ve karşılaştırmanın gerçekleşmesi için sıralama işlevi istenen indeksle yeniden tanımlandı.

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 ve @ vikas-gautam'ın omuzlarında durarak, OP'deki gibi bir sütunun dizeleri varsa gerekli olan sicim testini ekledim.

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

Test isNaN(a-b), dizelerin sayılara zorlanıp uygulanamayacağını belirler. Yapabilirlerse a-btest geçerlidir.

Karma türlerden oluşan bir sütunu sıralamanın her zaman eğlenceli bir sonuç vereceğini unutmayın, çünkü katı eşitlik testi (a === b)her zaman yanlış döndürür. MDN'yi burada görün

Bu, Google Apps Komut Dosyası kullanan Logger testi içeren tam komut dosyasıdır.

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

}

Olası ilginin güncellenmesi - 2 Temmuz 2019. Sıralama artık 'kararlı'. Burayı oku. (Mathias BynensVerified @mathias) v8.dev/features/stable-sort
DeeKay789
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.