Bir diziyi birden çok sütun üzerinde nasıl sıralarsınız?


119

Çok boyutlu bir dizilim var. Birincil dizi bir dizidir

[publicationID][publication_name][ownderID][owner_name] 

Yapmaya çalıştığım şey, diziyi sırasıyla owner_nameve sonra sıralamak publication_name. JavaScript'te Array.sort(), içine özel bir işlev koyabileceğiniz biliyorum , benim durumumda:

function mysortfunction(a, b) {
    var x = a[3].toLowerCase();
    var y = b[3].toLowerCase();

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

Bu sadece yani OWNER_NAME, bir sütun üzerinde sıralamak için iyi, ama nasıl bunu üzerine sıralamak için değiştiririm owner_name, sonra publication_name?

Yanıtlar:


167

Sahip isimleri farklıysa, onlara göre sıralayın. Aksi takdirde, eşitlik bozucu için yayın adını kullanın.

function mysortfunction(a, b) {

  var o1 = a[3].toLowerCase();
  var o2 = b[3].toLowerCase();

  var p1 = a[1].toLowerCase();
  var p2 = b[1].toLowerCase();

  if (o1 < o2) return -1;
  if (o1 > o2) return 1;
  if (p1 < p2) return -1;
  if (p1 > p2) return 1;
  return 0;
}

@dcp İkinci niteliği de nasıl sıralayabildiğini anlamıyorum. Seçili sütun sayısı kadar döngü yapmadığınız sürece .. Haklı mıyım? örneğin[[A, 10], [J, 15], [A, 5], [J, 5]] => [[A, 10], [A, 5], [J, 15], [J, 5]]
Bla ...

2
@ user26409021 - Hayır, bu doğru değil. [[A, 5], [A, 10], [J, 5], [J, 15]] olur. Önce birinci özniteliğe göre, bunlar aynıysa ikinci özniteliğe göre sıralar. Yani örneğinizde, A, J'den önce gelirdi. A'nın iki öğe için aynı olması durumunda, ikinci niteliği kullanır. Dolayısıyla [A, 10], [A, 5] için 5, 10'dan önce gelir, böylece sıralama için [A, 5], [A, 10] ile sonuçlanır. Eksik olabileceğiniz şey, sıralama tamamlanana kadar Array.sort'u kullandığınızda mysort function'ın birden çok kez çağrılmasıdır.
dcp

3
@ user26409021 - mysortfunction işlevinde bir döngüye gerek yoktur çünkü Array.sort, Dizi düzgün şekilde sıralanana kadar işlevi gerektiği gibi çağıracaktır. Mysortfunction'nun sorumlu olduğu tek şey, a ve b argümanlarının eşit olup olmadığını, a'nın b'den küçük olup olmadığını veya a'nın b'den büyük olup olmadığını belirlemektir. Bu tespiti yapmak için bir döngüye ihtiyacımız yok. Umarım yardımcı olur.
dcp

58

Sanırım aradığınız şey thenBy.js: https://github.com/Teun/thenBy.js

Standart Array.sort'u firstBy().thenBy().thenBy()stille birlikte kullanmanıza izin verir .

Burada bir örnek görülebilir .


Büyük veri kümelerinde performans konusunda dikkatli olun. Her thenByçağrıldığında, tüm dizi öğeleri tekrar döngüye girer.
Ray Shan

6
Durum kesinlikle bu değil. ThenBy () 'yi çağırdığınızda, öncekini içine alan yeni bir işlev oluşturur. Sıralama zamanda, JavaScript kesinlikle öğeler "döngü", ancak alışkanlık olacak birçok kez geçmek işlevini çağırın. ThenBy kullanılarak çağrı sayısı değişmeyecektir. Bazı performans değerlendirmeleri için şunu okuyun: github.com/Teun/thenBy.js#a-word-on-performance
Teun D

2
Anlıyorum, yanılmışım, performansı düşündüğün için teşekkürler. Belki de yeni işlevlerle kapanışlar oluşturmanın bellek konuları hakkında bir not ekleyin?
Ray Shan

O halde bunu çoklu dinamik için nasıl kullanabilirim? veya for döngüsünde mi?
Hemil Patel

@Harry Çalışmasını sağlayamıyorsanız, lütfen örnekle sıralayamayacağınız bir sorun gönderin, böylece diğerleri de öğrenebilir. Sana yardım etmekten mutluluk duyarım. github.com/Teun/thenBy.js/issues
Teun D

35

Dize olan birçok alanı sıralamanın iyi bir yolu toLocaleCompare, boolean operatörünü kullanmaktır ||.

Gibi bir şey:

// Sorting record releases by name and then by title.
releases.sort((oldRelease, newRelease) => {
  const compareName = oldRelease.name.localeCompare(newRelease.name);
  const compareTitle = oldRelease.title.localeCompare(newRelease.title);

  return compareName || compareTitle;
})

Daha fazla alana göre sıralama yapmak isterseniz, onları daha fazla mantıksal operatörle return deyiminden zincirleyebilirsiniz.


.reduce()
aslına bakarsan

ancak, .localCompare()bir -1, 0, 1 döndürür, bu yüzden çözümünüzün ||
boole'lar

10
@ekkis, hem 1 hem de -1 "doğru", bu yüzden bu çok zarif bir çözüm. Bunu daha yeni yaptım sortItems = (a, b) => (a.distance - b.distance) || (a.name - b.name); ve seçici olmayan ihtiyaçlarım için bir cazibe gibi çalışıyor.
bstst

1
@bstst senin yolun daha iyidir, çünkü (a.name - b.name)gerekli olmadıkça değerlendirmez . Önce değişkenler oluşturmak, gerekli olmasa bile fazladan iş yapar.
andi

Doğru, bu gereğinden fazla iş yapıyor, ancak bunu yalnızca kritik alanlarda değiştirirdim. Nominal miktarda veriyi sıralayan kod için, kod netliği performansın önüne geçer.
tbranyen

27

Anahtarlara göre SQL tarzı karışık asc ve desc nesne dizisi sıralaması yapma ihtiyacı doğdu.

kennebec'in yukarıdaki çözümü şuna ulaşmama yardımcı oldu:

Array.prototype.keySort = function(keys) {

keys = keys || {};

// via
// /programming/5223/length-of-javascript-object-ie-associative-array
var obLen = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key))
            size++;
    }
    return size;
};

// avoiding using Object.keys because I guess did it have IE8 issues?
// else var obIx = function(obj, ix){ return Object.keys(obj)[ix]; } or
// whatever
var obIx = function(obj, ix) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (size == ix)
                return key;
            size++;
        }
    }
    return false;
};

var keySort = function(a, b, d) {
    d = d !== null ? d : 1;
    // a = a.toLowerCase(); // this breaks numbers
    // b = b.toLowerCase();
    if (a == b)
        return 0;
    return a > b ? 1 * d : -1 * d;
};

var KL = obLen(keys);

if (!KL)
    return this.sort(keySort);

for ( var k in keys) {
    // asc unless desc or skip
    keys[k] = 
            keys[k] == 'desc' || keys[k] == -1  ? -1 
          : (keys[k] == 'skip' || keys[k] === 0 ? 0 
          : 1);
}

this.sort(function(a, b) {
    var sorted = 0, ix = 0;

    while (sorted === 0 && ix < KL) {
        var k = obIx(keys, ix);
        if (k) {
            var dir = keys[k];
            sorted = keySort(a[k], b[k], dir);
            ix++;
        }
    }
    return sorted;
});
return this;
};

örnek kullanım:

var obja = [
  {USER:"bob",  SCORE:2000, TIME:32,    AGE:16, COUNTRY:"US"},
  {USER:"jane", SCORE:4000, TIME:35,    AGE:16, COUNTRY:"DE"},
  {USER:"tim",  SCORE:1000, TIME:30,    AGE:17, COUNTRY:"UK"},
  {USER:"mary", SCORE:1500, TIME:31,    AGE:19, COUNTRY:"PL"},
  {USER:"joe",  SCORE:2500, TIME:33,    AGE:18, COUNTRY:"US"},
  {USER:"sally",    SCORE:2000, TIME:30,    AGE:16, COUNTRY:"CA"},
  {USER:"yuri", SCORE:3000, TIME:34,    AGE:19, COUNTRY:"RU"},
  {USER:"anita",    SCORE:2500, TIME:32,    AGE:17, COUNTRY:"LV"},
  {USER:"mark", SCORE:2000, TIME:30,    AGE:18, COUNTRY:"DE"},
  {USER:"amy",  SCORE:1500, TIME:29,    AGE:19, COUNTRY:"UK"}
];

var sorto = {
  SCORE:"desc",TIME:"asc", AGE:"asc"
};

obja.keySort(sorto);

aşağıdakileri verir:

 0: {     USER: jane;     SCORE: 4000;    TIME: 35;       AGE: 16;    COUNTRY: DE;   }
 1: {     USER: yuri;     SCORE: 3000;    TIME: 34;       AGE: 19;    COUNTRY: RU;   }
 2: {     USER: anita;    SCORE: 2500;    TIME: 32;       AGE: 17;    COUNTRY: LV;   }
 3: {     USER: joe;      SCORE: 2500;    TIME: 33;       AGE: 18;    COUNTRY: US;   }
 4: {     USER: sally;    SCORE: 2000;    TIME: 30;       AGE: 16;    COUNTRY: CA;   }
 5: {     USER: mark;     SCORE: 2000;    TIME: 30;       AGE: 18;    COUNTRY: DE;   }
 6: {     USER: bob;      SCORE: 2000;    TIME: 32;       AGE: 16;    COUNTRY: US;   }
 7: {     USER: amy;      SCORE: 1500;    TIME: 29;       AGE: 19;    COUNTRY: UK;   }
 8: {     USER: mary;     SCORE: 1500;    TIME: 31;       AGE: 19;    COUNTRY: PL;   }
 9: {     USER: tim;      SCORE: 1000;    TIME: 30;       AGE: 17;    COUNTRY: UK;   }
 keySort: {  }

( buradan bir yazdırma işlevi kullanarak )

işte bir jsbin örneği .

edit: temizlendi ve github'da mksort.js olarak yayınlandı .


17

Bu, tüm boyutlardaki alfa türleri için kullanışlıdır. Sıralamak istediğiniz dizinleri bağımsız değişken olarak geçirin.

Array.prototype.deepSortAlpha= function(){
    var itm, L=arguments.length, order=arguments;

    var alphaSort= function(a, b){
        a= a.toLowerCase();
        b= b.toLowerCase();
        if(a== b) return 0;
        return a> b? 1:-1;
    }
    if(!L) return this.sort(alphaSort);

    this.sort(function(a, b){
        var tem= 0,  indx=0;
        while(tem==0 && indx<L){
            itm=order[indx];
            tem= alphaSort(a[itm], b[itm]); 
            indx+=1;        
        }
        return tem;
    });
    return this;
}

var arr= [[ "Nilesh","Karmshil"], ["Pranjal","Deka"], ["Susants","Ghosh"],
["Shiv","Shankar"], ["Javid","Ghosh"], ["Shaher","Banu"], ["Javid","Rashid"]];

arr.deepSortAlpha(1,0);

Bu verileri nereden topladığınızı öğrenebilir miyim [["Nilesh", "Karmshil"], ["Pranjal", "Deka"], ["Susants", "Ghosh"], ["Shiv", "Shankar"] , ["Javid", "Ghosh"], ["Shaher", "Banu"], ["Javid", "Rashid"]];
defau1t

11

Yerleşik bir karşılaştırıcı kullanmanızı ve istenen sıralama düzenini mantıksal veya ||.

function customSort(a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
}

Çalışma örneği:

var array = [
    [0, 'Aluminium', 0, 'Francis'],
    [1, 'Argon', 1, 'Ada'],
    [2, 'Brom', 2, 'John'],
    [3, 'Cadmium', 3, 'Marie'],
    [4, 'Fluor', 3, 'Marie'],
    [5, 'Gold', 1, 'Ada'],
    [6, 'Kupfer', 4, 'Ines'],
    [7, 'Krypton', 4, 'Joe'],
    [8, 'Sauerstoff', 3, 'Marie'],
    [9, 'Zink', 5, 'Max']
];

array.sort(function (a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
});

document.write('<pre>');
array.forEach(function (a) {
    document.write(JSON.stringify(a) + '<br>');
});


Bu benim için harika çalıştı! Anlaması da basit. Teşekkürler!
DanCue

Budur!!! *****
Fredrik Johansson

8

2 değişkeni bir sıralama anahtarına birleştirebilir ve bunu karşılaştırmanız için kullanabilirsiniz.

list.sort(function(a,b){
   var aCat = a.var1 + a.var2;
   var bCat = b.var1 + b.var2;
   return (aCat > bCat ? 1 : aCat < bCat ? -1 : 0);
});

@GustavoRodrigues belki çok kırılgan olduğu için. Bir sınırlayıcı veya başka bir ayrım olmadan iki parçayı bir araya getirdiğinden, belirli giriş anahtarlarında beklenen şekilde sıralama yapamaz. X öğesi için var1 ve var2'nin "foo" ve "baz", Y öğesi için var1'in "foobar" olup olmadığını düşünün. Sıralandığında X önce gelmelidir, ancak bu durumda ikinci olur. Bu cevap geliştirilebilir, ancak belirtildiği gibi güvenli değildir.
Peter Hansen

4

Multisotr buldum . Bu, çoklu sıralama için basit, güçlü ve küçük bir kitaplıktır. Dinamik sıralama kriterlerine göre bir dizi nesneyi sıralamam gerekiyordu:

const criteria = ['name', 'speciality']
const data = [
  { name: 'Mike', speciality: 'JS', age: 22 },
  { name: 'Tom', speciality: 'Java', age: 30 },
  { name: 'Mike', speciality: 'PHP', age: 40 },
  { name: 'Abby', speciality: 'Design', age: 20 },
]

const sorted = multisort(data, criteria)

console.log(sorted)
<script src="https://cdn.rawgit.com/peterkhayes/multisort/master/multisort.js"></script>

Bu kütüphane daha güçlü, benim durumumdu. Dene.


2

ng-gridBir API'den döndürülen bir dizi kayıt üzerinde birden çok sütun sıralamasıyla çalışıyordum ve buna ihtiyacım vardı, bu yüzden bu şık, dinamik çok sıralama işlevini buldum.

Her şeyden önce, ng-grid"ngGridSorted" için bir "olay" tetikler ve bu yapıyı geri vererek sıralamayı açıklar:

sortData = {
    columns:    DOM Element,
    directions: [], //Array of string values desc or asc. Each index relating to the same index of fields
    fields:     [], //Array of string values
};

Bu yüzden, sortDatayukarıda gösterildiği gibi dinamik olarak bir sıralama işlevi oluşturacak bir işlev geliştirdim ( Kaydırma çubuğundan korkmayın! Yalnızca yaklaşık 50 satır uzunluğunda! Ayrıca, eğim için üzgünüm. Yatay bir kaydırma çubuğu! ):

function SortingFunction(sortData)
{
    this.sortData = sortData;

    this.sort = function(a, b)
    {
        var retval = 0;

        if(this.sortData.fields.length)
        {
            var i = 0;

            /*
                Determine if there is a column that both entities (a and b)
                have that are not exactly equal. The first one that we find
                will be the column we sort on. If a valid column is not
                located, then we will return 0 (equal).
            */
            while(  (   !a.hasOwnProperty(this.sortData.fields[i]) 
                    ||  !b.hasOwnProperty(this.sortData.fields[i]) 
                    ||  (a.hasOwnProperty(this.sortData.fields[i]) 
                        && b.hasOwnProperty(this.sortData.fields[i]) 
                        && a[this.sortData.fields[i]] === b[this.sortData.fields[i]])
                    ) && i < this.sortData.fields.length){
                i++;
            }

            if(i < this.sortData.fields.length)
            {
                /*
                    A valid column was located for both entities
                    in the SortData. Now perform the sort.
                */
                if(this.sortData.directions 
                && i < this.sortData.directions.length 
                && this.sortData.directions[i] === 'desc')
                {
                    if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
                        retval = -1;
                    else if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
                        retval = 1;
                }
                else
                {
                    if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
                        retval = -1;
                    else if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
                        retval = 1;
                }
            }
        }

        return retval;
    }.bind(this);
}

Daha sonra API'min ( results) sonuçlarını şöyle sıralıyorum :

results.sort(new SortingFunction(sortData).sort);

Umarım bu çözümü benim kadar başkası da beğenir! Teşekkürler!


sıralama verilerindeki sütunlar seçeneği ne için kullanılır?
Alex Hope O'Connor

2

Bunu dene:

t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );

let t = [ [publicationID, publication_name, ownderID, owner_name ], ... ]Dizideki verilerinizin sahip_adı = 3 ve yayın_adı = 1 dizinlerinde olduğunu varsayıyorum.


2

Dize Ekleme Yöntemi

Değerleri bir dizeye ekleyerek ve dizeleri karşılaştırarak birden çok değere göre sıralayabilirsiniz. Bir tuştan diğerine akmayı önlemek için bölünmüş bir anahtar karakter eklemek faydalıdır.

Misal

const arr = [ 
    { a: 1, b: 'a', c: 3 },
    { a: 2, b: 'a', c: 5 },
    { a: 1, b: 'b', c: 4 },
    { a: 2, b: 'a', c: 4 }
]


function sortBy (arr, keys, splitKeyChar='~') {
    return arr.sort((i1,i2) => {
        const sortStr1 = keys.reduce((str, key) => str + splitKeyChar+i1[key], '')
        const sortStr2 = keys.reduce((str, key) => str + splitKeyChar+i2[key], '')
        return sortStr1.localeCompare(sortStr2)
    })
}

console.log(sortBy(arr, ['a', 'b', 'c']))


1
function multiSort() {

    var args =$.makeArray( arguments ),
        sortOrder=1, prop='', aa='',  b='';

    return function (a, b) {

       for (var i=0; i<args.length; i++){

         if(args[i][0]==='-'){
            prop=args[i].substr(1)
            sortOrder=-1
         }
         else{sortOrder=1; prop=args[i]}

         aa = a[prop].toLowerCase()
         bb = b[prop].toLowerCase()

         if (aa < bb) return -1 * sortOrder;
         if (aa > bb) return 1 * sortOrder;

       }

       return 0
    }

}
empArray.sort(multiSort( 'lastname','firstname')) Reverse with '-lastname'

1

Bazı sanal DOM h fonksiyonları kompozisyonunun çıktısından bellek havuzu bloklarını görüntülerken benzer bir sorun yaşadım. Temel olarak, dünya çapındaki oyuncuların sonuçlarını puanlamak gibi çok kriterli verileri sıralamakla aynı problemle karşılaştım.

Çok kriterli sıralamanın şu şekilde olduğunu fark ettim:

- sort by the first column
- if equal, sort by the second
- if equal, sort by the third
-  etc... nesting and nesting if-else

Ve eğer umursamazsan, başka türlü iç içe geçmiş bir cehennemde çabucak başarısız olabilirsin ... sözlerin cehennemini geri aramak gibi ...

Alternatifin hangi kısmının kullanılıp kullanılmayacağına karar vermek için bir "yüklem" işlevi yazarsak ne olur? Yüklem basitçe:

// useful for chaining test
const decide = (test, other) => test === 0 ? other : test

Şimdi, sınıflandırma testlerinizi (byCountrySize, byAge, byGameType, byScore, byLevel ...) yazdıktan sonra, kimin ihtiyacı olursa olsun, testlerinizi ağırlıklandırabilirsiniz (1 = asc, -1 = desc, 0 = disable), onları bir diziye koyun ve aşağıdaki gibi azaltıcı bir 'karar verme' işlevi uygulayın:

const multisort = (s1, s2) => {
  const bcs = -1 * byCountrySize(s1, s2) // -1 = desc 
  const ba =  1 *byAge(s1, s2)
  const bgt = 0 * byGameType(s1, s2) // 0 = doesn't matter
  const bs = 1 * byScore(s1, s2)
  const bl = -1 * byLevel(s1, s2) // -1 = desc

  // ... other weights and criterias

  // array order matters !
  return [bcs, ba, bgt, bs, bl].reduce((acc, val) => decide(val, acc), 0)
}

// invoke [].sort with custom sort...
scores.sort(multisort)

Ve voila! Kendi kriterlerinizi / ağırlıklarınızı / siparişlerinizi tanımlamak size kalmış ... ama siz anladınız. Bu yardımcı olur umarım !

DÜZENLEME: * her sütunda toplam bir sıralama düzeni olduğundan emin olun * sütun sıraları arasında bağımlılık olmadığından ve döngüsel bağımlılık olmadığından emin olun

değilse, sıralama istikrarsız olabilir!


1

ES6 yinelemeleri (blinq) ile çalışmak için kendi kitaplığım (diğer şeylerin yanı sıra) kolay çok seviyeli sıralama sağlar

const blinq = window.blinq.blinq
// or import { blinq } from 'blinq'
// or const { blinq } = require('blinq')
const dates = [{
    day: 1, month: 10, year: 2000
  },
  {
    day: 1, month: 1, year: 2000
  },
  {
    day: 2, month: 1, year: 2000
  },
  {
    day: 1, month: 1, year: 1999
  },
  {
    day: 1, month: 1, year: 2000
  }
]
const sortedDates = blinq(dates)
  .orderBy(x => x.year)
  .thenBy(x => x.month)
  .thenBy(x => x.day);

console.log(sortedDates.toArray())
// or console.log([...sortedDates])
<script src="https://cdn.jsdelivr.net/npm/blinq@2.0.2"></script>


0

GitHub kaynaklı

function sortMethodAsc(a, b) {
    return a == b ? 0 : a > b ? 1 : -1;
}

function sortMethodWithDirection(direction) { 
    if (direction === undefined || direction == "asc") {
        return sortMethodAsc;
    } else {
        return function(a, b) {
            return -sortMethodAsc(a, b);
        } 
    }
}

function sortMethodWithDirectionByColumn(columnName, direction){   
    const sortMethod = sortMethodWithDirection(direction)
    return function(a, b){
        return sortMethod(a[columnName], b[columnName]);
    } 
}

function sortMethodWithDirectionMultiColumn(sortArray) {
    //sample of sortArray
    // sortArray = [
    //     { column: "column5", direction: "asc" },
    //     { column: "column3", direction: "desc" }
    // ]
    const sortMethodsForColumn = (sortArray || []).map( item => sortMethodWithDirectionByColumn(item.column, item.direction) );
    return function(a,b) {
        let sorted = 0;
        let index = 0;
        while (sorted === 0 && index < sortMethodsForColumn.length) {
            sorted = sortMethodsForColumn[index++](a,b);
        }
        return sorted;
    }
} 

//=============================================
//=============================================
//=============================================
//test

var data = [
    {"CountryName":"Aruba","CountryCode":"ABW","GNI":280},{
        "CountryName":"Afghanistan","CountryCode":"ABW","GNI":280},{"CountryName":"Angola","CountryCode":"AGO","GNI":280},{"CountryName":"Albania","CountryCode":"ALB","GNI":4320},
        {"CountryName":"Arab World","CountryCode":"ARB","GNI":280},{"CountryName":"United Arab Emirates","CountryCode":"ARE","GNI":39130},
        {"CountryName":"Argentina","CountryCode":"ARG","GNI":13030},{"CountryName":"Armenia","CountryCode":"ARM","GNI":3990},{"CountryName":"American Samoa","CountryCode":"ASM","GNI":280},
        {"CountryName":"Antigua and Barbuda","CountryCode":"ATG","GNI":13810},{"CountryName":"Australia","CountryCode":"AUS","GNI":51360},
        {"CountryName":"Austria","CountryCode":"AUT","GNI":45440},{"CountryName":"Azerbaijan","CountryCode":"AZE","GNI":4080},{"CountryName":"Burundi","CountryCode":"BDI","GNI":280},
        {"CountryName":"Belgium","CountryCode":"BEL","GNI":41790},{"CountryName":"Benin","CountryCode":"BEN","GNI":800},{"CountryName":"Burkina Faso","CountryCode":"BFA","GNI":590},
        {"CountryName":"Bangladesh","CountryCode":"BGD","GNI":1470},{"CountryName":"Bulgaria","CountryCode":"BGR","GNI":7860},{"CountryName":"Bahrain","CountryCode":"BHR","GNI":21150},
        {"CountryName":"Bosnia and Herzegovina","CountryCode":"BIH","GNI":4910},{"CountryName":"Belarus","CountryCode":"BLR","GNI":5280},
        {"CountryName":"Belize","CountryCode":"BLZ","GNI":4390},{"CountryName":"Bolivia","CountryCode":"BOL","GNI":3130},{"CountryName":"Brazil","CountryCode":"BRA","GNI":8600},
        {"CountryName":"Barbados","CountryCode":"BRB","GNI":15270},{"CountryName":"Brunei Darussalam","CountryCode":"BRN","GNI":29600},
        {"CountryName":"Bhutan","CountryCode":"BTN","GNI":2660},{"CountryName":"Botswana","CountryCode":"BWA","GNI":6730},
        {"CountryName":"Central African Republic","CountryCode":"CAF","GNI":390},{"CountryName":"Canada","CountryCode":"CAN","GNI":42870},
        {"CountryName":"Central Europe and the Baltics","CountryCode":"CEB","GNI":13009},{"CountryName":"Switzerland","CountryCode":"CHE","GNI":80560},
        {"CountryName":"Chile","CountryCode":"CHL","GNI":13610},{"CountryName":"China","CountryCode":"CHN","GNI":8690},{"CountryName":"Cote d'Ivoire","CountryCode":"CIV","GNI":1580},
        {"CountryName":"Cameroon","CountryCode":"CMR","GNI":1370},{"CountryName":"Colombia","CountryCode":"COL","GNI":5890},{"CountryName":"Comoros","CountryCode":"COM","GNI":1280},
        {"CountryName":"Cabo Verde","CountryCode":"CPV","GNI":3030},{"CountryName":"Costa Rica","CountryCode":"CRI","GNI":11120},
        {"CountryName":"Caribbean small states","CountryCode":"CSS","GNI":8909},{"CountryName":"Cyprus","CountryCode":"CYP","GNI":23720},
        {"CountryName":"Czech Republic","CountryCode":"CZE","GNI":18160},{"CountryName":"Germany","CountryCode":"DEU","GNI":43490},
        {"CountryName":"Djibouti","CountryCode":"DJI","GNI":1880},{"CountryName":"Dominica","CountryCode":"DMA","GNI":6590},{"CountryName":"Denmark","CountryCode":"DNK","GNI":55220},
        {"CountryName":"Dominican Republic","CountryCode":"DOM","GNI":6630},{"CountryName":"Algeria","CountryCode":"DZA","GNI":3940},
        {"CountryName":"East Asia & Pacific (excluding high income)","CountryCode":"EAP","GNI":6987},{"CountryName":"Early-demographic dividend","CountryCode":"EAR","GNI":3352},
        {"CountryName":"East Asia & Pacific","CountryCode":"EAS","GNI":10171},{"CountryName":"Europe & Central Asia (excluding high income)","CountryCode":"ECA","GNI":7375},
        {"CountryName":"Europe & Central Asia","CountryCode":"ECS","GNI":22656},{"CountryName":"Ecuador","CountryCode":"ECU","GNI":5920},
        {"CountryName":"Euro area","CountryCode":"EMU","GNI":35645},{"CountryName":"Spain","CountryCode":"ESP","GNI":27180},{"CountryName":"Estonia","CountryCode":"EST","GNI":18190},
        {"CountryName":"Ethiopia","CountryCode":"ETH","GNI":740},{"CountryName":"European Union","CountryCode":"EUU","GNI":32784},
        {"CountryName":"Fragile and conflict affected situations","CountryCode":"FCS","GNI":1510},{"CountryName":"Finland","CountryCode":"FIN","GNI":44580},
        {"CountryName":"Fiji","CountryCode":"FJI","GNI":4970},{"CountryName":"France","CountryCode":"FRA","GNI":37970},{"CountryName":"Gabon","CountryCode":"GAB","GNI":6650},
        {"CountryName":"United Kingdom","CountryCode":"GBR","GNI":40530},{"CountryName":"Georgia","CountryCode":"GEO","GNI":3780},{"CountryName":"Ghana","CountryCode":"GHA","GNI":1880},
        {"CountryName":"Guinea","CountryCode":"GIN","GNI":790},{"CountryName":"Guinea-Bissau","CountryCode":"GNB","GNI":660},
        {"CountryName":"Equatorial Guinea","CountryCode":"GNQ","GNI":7050},{"CountryName":"Greece","CountryCode":"GRC","GNI":18090},
        {"CountryName":"Grenada","CountryCode":"GRD","GNI":9180},{"CountryName":"Guatemala","CountryCode":"GTM","GNI":4060},{"CountryName":"Guyana","CountryCode":"GUY","GNI":4500},
        {"CountryName":"High income","CountryCode":"HIC","GNI":40142},{"CountryName":"Honduras","CountryCode":"HND","GNI":2250},{"CountryName":"Heavily indebted poor countries (HIPC)","CountryCode":"HPC","GNI":904},{"CountryName":"Croatia","CountryCode":"HRV","GNI":12570},{"CountryName":"Haiti","CountryCode":"HTI","GNI":760},{"CountryName":"Hungary","CountryCode":"HUN","GNI":12870},{"CountryName":"IBRD only","CountryCode":"IBD","GNI":5745},{"CountryName":"IDA & IBRD total","CountryCode":"IBT","GNI":4620},{"CountryName":"IDA total","CountryCode":"IDA","GNI":1313},{"CountryName":"IDA blend","CountryCode":"IDB","GNI":1791},
        {"CountryName":"Indonesia","CountryCode":"IDN","GNI":3540},{"CountryName":"IDA only","CountryCode":"IDX","GNI":1074},{"CountryName":"India","CountryCode":"IND","GNI":1800},{"CountryName":"Ireland","CountryCode":"IRL","GNI":55290},{"CountryName":"Iraq","CountryCode":"IRQ","GNI":4630},{"CountryName":"Iceland","CountryCode":"ISL","GNI":60830},{"CountryName":"Israel","CountryCode":"ISR","GNI":37270},{"CountryName":"Italy","CountryCode":"ITA","GNI":31020},{"CountryName":"Jamaica","CountryCode":"JAM","GNI":4760},{"CountryName":"Jordan","CountryCode":"JOR","GNI":3980},{"CountryName":"Japan","CountryCode":"JPN","GNI":38550},{"CountryName":"Kazakhstan","CountryCode":"KAZ","GNI":7970},{"CountryName":"Kenya","CountryCode":"KEN","GNI":1460},{"CountryName":"Kyrgyz Republic","CountryCode":"KGZ","GNI":1130},
        {"CountryName":"Cambodia","CountryCode":"KHM","GNI":1230},{"CountryName":"Kiribati","CountryCode":"KIR","GNI":3010},{"CountryName":"St. Kitts and Nevis","CountryCode":"KNA","GNI":16240},{"CountryName":"Kuwait","CountryCode":"KWT","GNI":31430},{"CountryName":"Latin America & Caribbean (excluding high income)","CountryCode":"LAC","GNI":7470},{"CountryName":"Lao PDR","CountryCode":"LAO","GNI":2270},{"CountryName":"Lebanon","CountryCode":"LBN","GNI":8400},{"CountryName":"Liberia","CountryCode":"LBR","GNI":620},{"CountryName":"Libya","CountryCode":"LBY","GNI":5500},{"CountryName":"St. Lucia","CountryCode":"LCA","GNI":8830},{"CountryName":"Latin America & Caribbean","CountryCode":"LCN","GNI":8251},{"CountryName":"Least developed countries: UN classification","CountryCode":"LDC","GNI":1011},{"CountryName":"Low income","CountryCode":"LIC","GNI":774},{"CountryName":"Sri Lanka","CountryCode":"LKA","GNI":3850},{"CountryName":"Lower middle income","CountryCode":"LMC","GNI":2118},{"CountryName":"Low & middle income","CountryCode":"LMY","GNI":4455},{"CountryName":"Lesotho","CountryCode":"LSO","GNI":1210},{"CountryName":"Late-demographic dividend","CountryCode":"LTE","GNI":8518},{"CountryName":"Lithuania","CountryCode":"LTU","GNI":15200},{"CountryName":"Luxembourg","CountryCode":"LUX","GNI":70260},{"CountryName":"Latvia","CountryCode":"LVA","GNI":14740},{"CountryName":"Morocco","CountryCode":"MAR","GNI":2860},{"CountryName":"Moldova","CountryCode":"MDA","GNI":2200},{"CountryName":"Madagascar","CountryCode":"MDG","GNI":400},{"CountryName":"Maldives","CountryCode":"MDV","GNI":9760},
        {"CountryName":"Middle East & North Africa","CountryCode":"MEA","GNI":7236},{"CountryName":"Mexico","CountryCode":"MEX","GNI":8610},{"CountryName":"Marshall Islands","CountryCode":"MHL","GNI":4840},{"CountryName":"Middle income","CountryCode":"MIC","GNI":4942},{"CountryName":"Mali","CountryCode":"MLI","GNI":770},
        {"CountryName":"Malta","CountryCode":"MLT","GNI":24080},{"CountryName":"Myanmar","CountryCode":"MMR","GNI":1210},{"CountryName":"Middle East & North Africa (excluding high income)","CountryCode":"MNA","GNI":3832},{"CountryName":"Montenegro","CountryCode":"MNE","GNI":7400},{"CountryName":"Mongolia","CountryCode":"MNG","GNI":3270},{"CountryName":"Mozambique","CountryCode":"MOZ","GNI":420},{"CountryName":"Mauritania","CountryCode":"MRT","GNI":1100},{"CountryName":"Mauritius","CountryCode":"MUS","GNI":10130},{"CountryName":"Malawi","CountryCode":"MWI","GNI":320},{"CountryName":"Malaysia","CountryCode":"MYS","GNI":9650},{"CountryName":"North America","CountryCode":"NAC","GNI":56721},{"CountryName":"Namibia","CountryCode":"NAM","GNI":4570},{"CountryName":"Niger","CountryCode":"NER","GNI":360},{"CountryName":"Nigeria","CountryCode":"NGA","GNI":2100},
        {"CountryName":"Nicaragua","CountryCode":"NIC","GNI":2130},{"CountryName":"Netherlands","CountryCode":"NLD","GNI":46180},{"CountryName":"Norway","CountryCode":"NOR","GNI":75990},{"CountryName":"Nepal","CountryCode":"NPL","GNI":800},{"CountryName":"Nauru","CountryCode":"NRU","GNI":10220},{"CountryName":"New Zealand","CountryCode":"NZL","GNI":38970},{"CountryName":"OECD members","CountryCode":"OED","GNI":37273},{"CountryName":"Oman","CountryCode":"OMN","GNI":14440},{"CountryName":"Other small states","CountryCode":"OSS","GNI":12199},{"CountryName":"Pakistan","CountryCode":"PAK","GNI":1580},{"CountryName":"Panama","CountryCode":"PAN","GNI":13280},{"CountryName":"Peru","CountryCode":"PER","GNI":5960},{"CountryName":"Philippines","CountryCode":"PHL","GNI":3660},{"CountryName":"Palau","CountryCode":"PLW","GNI":12700},{"CountryName":"Papua New Guinea","CountryCode":"PNG","GNI":2340},{"CountryName":"Poland","CountryCode":"POL","GNI":12730},{"CountryName":"Pre-demographic dividend","CountryCode":"PRE","GNI":1379},{"CountryName":"Portugal","CountryCode":"PRT","GNI":19820},{"CountryName":"Paraguay","CountryCode":"PRY","GNI":5470},{"CountryName":"West Bank and Gaza","CountryCode":"PSE","GNI":3180},{"CountryName":"Pacific island small states","CountryCode":"PSS","GNI":3793},{"CountryName":"Post-demographic dividend","CountryCode":"PST","GNI":41609},{"CountryName":"Qatar","CountryCode":"QAT","GNI":60510},{"CountryName":"Romania","CountryCode":"ROU","GNI":10000},{"CountryName":"Russian Federation","CountryCode":"RUS","GNI":9230},{"CountryName":"Rwanda","CountryCode":"RWA","GNI":720},{"CountryName":"South Asia","CountryCode":"SAS","GNI":1729},{"CountryName":"Saudi Arabia","CountryCode":"SAU","GNI":20090},{"CountryName":"Sudan","CountryCode":"SDN","GNI":2380},{"CountryName":"Senegal","CountryCode":"SEN","GNI":1240},{"CountryName":"Singapore","CountryCode":"SGP","GNI":54530},{"CountryName":"Solomon Islands","CountryCode":"SLB","GNI":1920},{"CountryName":"Sierra Leone","CountryCode":"SLE","GNI":510},{"CountryName":"El Salvador","CountryCode":"SLV","GNI":3560},{"CountryName":"Serbia","CountryCode":"SRB","GNI":5180},{"CountryName":"Sub-Saharan Africa (excluding high income)","CountryCode":"SSA","GNI":1485},{"CountryName":"Sub-Saharan Africa","CountryCode":"SSF","GNI":1486},{"CountryName":"Small states","CountryCode":"SST","GNI":11099},{"CountryName":"Sao Tome and Principe","CountryCode":"STP","GNI":1770},{"CountryName":"Suriname","CountryCode":"SUR","GNI":5150},{"CountryName":"Slovak Republic","CountryCode":"SVK","GNI":16610},{"CountryName":"Slovenia","CountryCode":"SVN","GNI":22000},{"CountryName":"Sweden","CountryCode":"SWE","GNI":52590},{"CountryName":"Eswatini","CountryCode":"SWZ","GNI":2950},{"CountryName":"Seychelles","CountryCode":"SYC","GNI":14170},{"CountryName":"Chad","CountryCode":"TCD","GNI":640},{"CountryName":"East Asia & Pacific (IDA & IBRD countries)","CountryCode":"TEA","GNI":7061},
        {"CountryName":"Europe & Central Asia (IDA & IBRD countries)","CountryCode":"TEC","GNI":7866},{"CountryName":"Togo","CountryCode":"TGO","GNI":610},{"CountryName":"Thailand","CountryCode":"THA","GNI":5950},{"CountryName":"Tajikistan","CountryCode":"TJK","GNI":990},{"CountryName":"Turkmenistan","CountryCode":"TKM","GNI":6380},{"CountryName":"Latin America & the Caribbean (IDA & IBRD countries)","CountryCode":"TLA","GNI":8179},{"CountryName":"Timor-Leste","CountryCode":"TLS","GNI":1790},{"CountryName":"Middle East & North Africa (IDA & IBRD countries)","CountryCode":"TMN","GNI":3839},{"CountryName":"Tonga","CountryCode":"TON","GNI":4010},{"CountryName":"South Asia (IDA & IBRD)","CountryCode":"TSA","GNI":1729},
        {"CountryName":"Sub-Saharan Africa (IDA & IBRD countries)","CountryCode":"TSS","GNI":1486},{"CountryName":"Trinidad and Tobago","CountryCode":"TTO","GNI":15340},{"CountryName":"Tunisia","CountryCode":"TUN","GNI":3490},{"CountryName":"Turkey","CountryCode":"TUR","GNI":10940},{"CountryName":"Tuvalu","CountryCode":"TUV","GNI":4970},{"CountryName":"Tanzania","CountryCode":"TZA","GNI":910},{"CountryName":"Uganda","CountryCode":"UGA","GNI":600},{"CountryName":"Ukraine","CountryCode":"UKR","GNI":2390},{"CountryName":"Upper middle income","CountryCode":"UMC","GNI":8197},{"CountryName":"Uruguay","CountryCode":"URY","GNI":15250},{"CountryName":"United States","CountryCode":"USA","GNI":58270},{"CountryName":"Uzbekistan","CountryCode":"UZB","GNI":2000},{"CountryName":"St. Vincent and the Grenadines","CountryCode":"VCT","GNI":7390},{"CountryName":"Vietnam","CountryCode":"VNM","GNI":2160},{"CountryName":"Vanuatu","CountryCode":"VUT","GNI":2920},{"CountryName":"World","CountryCode":"WLD","GNI":10371},{"CountryName":"Samoa","CountryCode":"WSM","GNI":4090},{"CountryName":"Kosovo","CountryCode":"XKX","GNI":3900},
        {"CountryName":"South Africa","CountryCode":"ZAF","GNI":5430},{"CountryName":"Zambia","CountryCode":"ZMB","GNI":1290},{"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1170},
        {"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1171}];

    const sortMethod = sortMethodWithDirectionMultiColumn(
        [
            { column: "GNI", direction: "asc" },
            { column: "CountryCode", direction: "desc" }
        ]
    );
    let sortedData = data.sort(sortMethod);  
    
    
    console.log("sorted by: 1)column:GNI-asc, 2)column:CountryCode-desc") 
    console.table(sortedData);
    console.log(sortedData);
    


Stackoverflow'a hoş geldiniz. Sağladığınız yanıta ek olarak, lütfen bunun sorunu neden ve nasıl düzelttiğine dair kısa bir açıklama sağlayın.
jtate

0

Npm'ye sort-helper adında bir mikro kitaplık yayınladım ( kaynak github'da ) . Buradaki fikir, sıralanacak sütunları ifade etmenin birkaç yolu ile , söz dizimi aracılığıyla dizi yöntemi byiçin karşılaştırma işlevini oluşturmak üzere yardımcıyı içe aktarmaktır :sortitems.sort(by(column, ...otherColumns))

  • By tuşu : persons.sort(by('lastName', 'firstName')),
  • By selektör :dates.sort(by(x => x.toISOString())) ,
  • In azalan : [3, 2, 4, 1].sort(by(desc(n => n)))[3, 2, 1, 0] ,
  • Büyük / küçük harf dikkate alınmadan : ['B', 'D', 'c', 'a'].sort(by(ignoreCase(x => x))).join('')'aBcD'.

O güzel benzeyen ThenBy belirtilen bu cevap ancak bazı beğenisine fazla olabilir aşağıdakiler farklıdır:

  • Nesne yönelimli olmaktan daha işlevsel bir yaklaşım (bkz. thenByAkıcı API) ,
  • Bir sözdizimi biraz daha ayrıntılı ve yine de okunabilir, neredeyse SQL gibi doğal.
  • Tür güvenliği ve tür ifadeliğinden yararlanmak için tamamen TypeScript'te uygulanmıştır.
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.