Javascript diziyi iki alana göre sırala


92
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);      
    return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;
});

Dolayısıyla, yukarıdaki kod diziyi gsize göre - en küçüğünden en büyüğüne - sıralar. İyi çalışıyor. Ama gsize aynıysa, parlamaya göre sıralamak isterim.

Teşekkürler.


sort işlevi pozitif, negatif veya sıfır sonuca tepki verir. böylece sadece şunu yazabilirsiniz: "return aSize - bSize". daha basit ve okunabilir bir kod olacaktır.

Yanıtlar:


112
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);

    if(aSize == bSize)
    {
        return (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0;
    }
    else
    {
        return (aSize < bSize) ? -1 : 1;
    }
});

Diğer bazı cevaplar gösterilen olmayan bariz tekniklerine başvurmadan, ok sözdizimini kullanarak bu daha özlü yapmak için: grouperArray.sort((a, b) => a.gsize == b.gsize ? a.glow - b.glow : a.gsize - b.gsize. Kodun anlaşılmasını kolaylaştırmak için testi açık tutuyoruz ==.
ToolmakerSteve

171
grouperArray.sort(function (a, b) {   
    return a.gsize - b.gsize || a.glow - b.glow;
});

daha kısa versiyon


harika kısa yol! daha karmaşık bir çözümü bir araya
getirmeme

3
Güzel ve temiz! Sadece sayılar için işe yaradığı tek şey.
Afanasii Kurakin

Buradaki mantığı açıklayabilir misiniz?!. Benim için çalıştı sort an array with a key's value firstve sonrasort the result with another key's value
KTM

1
@KTM Mantık şu şekildedir: her iki gsize eşitse, koşulun ilk kısmı 0'a eşittir, bu yanlış olarak kabul edilir ve koşulun ikinci kısmı yürütülür.
Scalpweb

@Scalpweb Evet :) yani bu, herhangi bir sayıda anahtarla bir diziyi tek tek sıralamak için işe yarar mı? Güzel numara
KTM


14

Bunun bir süre önce sorulduğunu fark ettim, ancak çözümümü ekleyeceğimi düşündüm.

Bu işlev, sıralama yöntemlerini dinamik olarak üretir. sadece, artan veya azalan sırayı belirtmek için başına +/- eklenmiş her sıralanabilir alt özellik adını sağlayın. Süper yeniden kullanılabilir ve bir araya getirdiğiniz veri yapısı hakkında hiçbir şey bilmesine gerek yoktur. Aptalca bir kanıt haline getirilebilir - ancak gerekli görünmüyor.

function getSortMethod(){
    var _args = Array.prototype.slice.call(arguments);
    return function(a, b){
        for(var x in _args){
            var ax = a[_args[x].substring(1)];
            var bx = b[_args[x].substring(1)];
            var cx;

            ax = typeof ax == "string" ? ax.toLowerCase() : ax / 1;
            bx = typeof bx == "string" ? bx.toLowerCase() : bx / 1;

            if(_args[x].substring(0,1) == "-"){cx = ax; ax = bx; bx = cx;}
            if(ax != bx){return ax < bx ? -1 : 1;}
        }
    }
}

örnek kullanım:

items.sort (getSortMethod ('- fiyat', '+ öncelik', '+ ad'));

bu , bağlar en yüksek olan maddeye gidecek şekilde önce itemsen düşük ile sıralanır . öğe tarafından daha fazla bağ koptupricepriorityname

öğeler aşağıdaki gibi bir dizidir:

var items = [
    { name: "z - test item", price: "99.99", priority: 0, reviews: 309, rating: 2 },
    { name: "z - test item", price: "1.99", priority: 0, reviews: 11, rating: 0.5 },
    { name: "y - test item", price: "99.99", priority: 1, reviews: 99, rating: 1 },
    { name: "y - test item", price: "0", priority: 1, reviews: 394, rating: 3.5 },
    { name: "x - test item", price: "0", priority: 2, reviews: 249, rating: 0.5 } ...
];

canlı demo: http://gregtaff.com/misc/multi_field_sort/

DÜZENLEME: Chrome ile ilgili sorun düzeltildi.


Bu harika
Azure

Dahi cevap!
Marius

error TS2554: Expected 0 arguments, but got ..
typcript

6

Üçlü operatörün kafanı((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;) karıştırdığını tahmin ediyorum . Daha iyi anlamak için bağlantıya göz atmalısınız.

O zamana kadar, işte kodunuz tam if / else şeklinde ortaya çıktı.

grouperArray.sort(function (a, b) {
    if (a.gsize < b.gsize)
    {
        return -1;
    }
    else if (a.gsize > b.gsize)
    {
        return 1;
    }
    else
    {
        if (a.glow < b.glow)
        {
            return -1;
        }
        else if (a.glow > b.glow)
        {
            return 1;
        }
        return 0;
    }
});

6

Herhangi bir sayıda alanla çalışacak daha genel bir şey isteyenler için bir uygulama.

Array.prototype.sortBy = function (propertyName, sortDirection) {

    var sortArguments = arguments;
    this.sort(function (objA, objB) {

        var result = 0;
        for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {

            var propertyName = sortArguments[argIndex];
            result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;

            //Reverse if sort order is false (DESC)
            result *= !sortArguments[argIndex + 1] ? 1 : -1;
        }
        return result;
    });

}

Temel olarak, istediğiniz sayıda özellik adı / sıralama yönü belirtebilirsiniz:

var arr = [{
  LastName: "Doe",
  FirstName: "John",
  Age: 28
}, {
  LastName: "Doe",
  FirstName: "Jane",
  Age: 28
}, {
  LastName: "Foo",
  FirstName: "John",
  Age: 30
}];

arr.sortBy("LastName", true, "FirstName", true, "Age", false);
//Will return Jane Doe / John Doe / John Foo

arr.sortBy("Age", false, "LastName", true, "FirstName", false);
//Will return John Foo / John Doe / Jane Doe

3
grouperArray.sort(function (a, b) {
  var aSize = a.gsize;
  var bSize = b.gsize;
  var aLow = a.glow;
  var bLow = b.glow;
  console.log(aLow + " | " + bLow);      
  return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : ( (aLow < bLow ) ? -1 : (aLow > bLow ) ? 1 : 0 );
});

3
grouperArray.sort(function (a, b) {
     var aSize = a.gsize;     
     var bSize = b.gsize;     
     var aLow = a.glow;
     var bLow = b.glow;
     console.log(aLow + " | " + bLow);
     return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0); }); 

3

Burada, 1'den sonsuza kadar herhangi bir sayıda sıralama alanına göre sıralamak için özyinelemeyi kullanan bir uygulama var. Sıralanacak sonuç nesneleri dizisi olan bir sonuç dizisi ve sıralamayı tanımlayan sıralama nesneleri dizisi olan bir sıralama dizisi geçirirsiniz. Her sıralama nesnesi, sıraladığı anahtar adı için bir "seçme" anahtarına ve "artan" veya "azalan" ifadesini gösteren bir dize olan bir "sıralama" anahtarına sahip olmalıdır.

sortMultiCompare = (a, b, sorts) => {
    let select = sorts[0].select
    let order = sorts[0].order
    if (a[select] < b[select]) {
        return order == 'ascending' ? -1 : 1
    } 
    if (a[select] > b[select]) {
        return order == 'ascending' ? 1 : -1
    }
    if(sorts.length > 1) {
        let remainingSorts = sorts.slice(1)
        return this.sortMultiCompare(a, b, remainingSorts)
    }
    return 0
}

sortResults = (results, sorts) => {
    return results.sort((a, b) => {
        return this.sortMultiCompare(a, b, sorts)
    })
}

// example inputs
const results = [
    {
        "LastName": "Doe",
        "FirstName": "John",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Doe",
        "FirstName": "Jane",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Johnson",
        "FirstName": "Kevin",
        "MiddleName": "Bill"
    }
]

const sorts = [
    {
        "select": "LastName",
        "order": "ascending"
    },
    {
        "select": "FirstName",
        "order": "ascending"
    },
    {
        "select": "MiddleName",
        "order": "ascending"
    }    
]

// call the function like this:
let sortedResults = sortResults(results, sorts)

2

ÇOKLU tuşlarla bunu yapmanın dinamik bir yolu:

  • sıralama her sütun / anahtarından benzersiz değerleri filtreleyin
  • sıraya koy ya da tersine çevir
  • indexOf (değer) anahtar değerlerine göre her nesne için ağırlık genişliği sıfırlama değeri ekleyin
  • hesaplanmış ağırlıkları kullanarak sıralama

görüntü açıklamasını buraya girin

Object.defineProperty(Array.prototype, 'orderBy', {
value: function(sorts) { 
    sorts.map(sort => {            
        sort.uniques = Array.from(
            new Set(this.map(obj => obj[sort.key]))
        );

        sort.uniques = sort.uniques.sort((a, b) => {
            if (typeof a == 'string') {
                return sort.inverse ? b.localeCompare(a) : a.localeCompare(b);
            }
            else if (typeof a == 'number') {
                return sort.inverse ? (a < b) : (a > b ? 1 : 0);
            }
            else if (typeof a == 'boolean') {
                let x = sort.inverse ? (a === b) ? 0 : a? -1 : 1 : (a === b) ? 0 : a? 1 : -1;
                return x;
            }
            return 0;
        });
    });

    const weightOfObject = (obj) => {
        let weight = "";
        sorts.map(sort => {
            let zeropad = `${sort.uniques.length}`.length;
            weight += sort.uniques.indexOf(obj[sort.key]).toString().padStart(zeropad, '0');
        });
        //obj.weight = weight; // if you need to see weights
        return weight;
    }

    this.sort((a, b) => {
        return weightOfObject(a).localeCompare( weightOfObject(b) );
    });

    return this;
}
});

Kullanım:

// works with string, number and boolean
let sortered = your_array.orderBy([
    {key: "type", inverse: false}, 
    {key: "title", inverse: false},
    {key: "spot", inverse: false},
    {key: "internal", inverse: true}
]);

görüntü açıklamasını buraya girin


1

Bu benim kullandığım şey

function sort(a, b) {
    var _a = "".concat(a.size, a.glow);
    var _b = "".concat(b.size, b.glow);
    return _a < _b;
}

iki öğeyi bir dizge olarak birleştirin ve bir dize değerine göre sıralanırlar. İsterseniz _a ve _b'yi parseInt ile sararak sayısal olacaklarını biliyorsanız, sayı olarak karşılaştırabilirsiniz.


1

Burada, bazı belirli öğelerde bulunmayabilecek bir öncelik sıralama anahtarına sahip olduğunuz, bu nedenle geri dönüş anahtarlarına göre sıralamanız gereken durum için çözüm bulunmaktadır.

Bir giriş verisi örneği ( id2 , öncelikli sıralama anahtarıdır):

const arr = [
    {id: 1},
    {id: 2, id2: 3},
    {id: 4},
    {id: 3},
    {id: 10, id2: 2},
    {id: 7},
    {id: 6, id2: 1},
    {id: 5},
    {id: 9, id2: 2},
    {id: 8},
];

Ve çıktı şöyle olmalıdır:

[ { id: 6, id2: 1 },
  { id: 9, id2: 2 },
  { id: 10, id2: 2 },
  { id: 2, id2: 3 },
  { id: 1 },
  { id: 3 },
  { id: 4 },
  { id: 5 },
  { id: 7 },
  { id: 8 } ]

Karşılaştırma işlevi şöyle olacaktır:

arr.sort((a,b) => {
  if(a.id2 || b.id2) {
    if(a.id2 && b.id2) {
      if(a.id2 === b.id2) {
        return a.id - b.id;
      }
      return a.id2 - b.id2;
    }
    return a.id2 ? -1 : 1;
  }
  return a.id - b.id
});

Eğer PS In case .kimlik ait .id2 sıfır olabilir kullanmayı düşünün typeof.


0
grouperArray.sort(
  function(a,b){return a.gsize == b.gsize ? a.glow - b.glow : a.gsize - b.gsize}
);

0
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    if (aSize !== aSize)
        return aSize - bSize;
    return a.glow - b.glow;
});

test edilmedi, ama bunun işe yarayacağını düşünüyorum.


0

Benim durumumda, bildirim listesini 'önemli' parametresine ve 'tarihe' göre sıralıyorum

  • 1. adım: Bildirimleri "önemli" ve önemsiz ölçütlerine göre filtreliyorum

    let importantNotifications = notifications.filter(
            (notification) => notification.isImportant);
    
      let unImportantNotifications = notifications.filter(
            (notification) => !notification.isImportant);
    
  • 2. adım: onları tarihe göre sıralıyorum

      sortByDate = (notifications) => {
      return notifications.sort((notificationOne, notificationTwo) => {
        return notificationOne.date - notificationTwo.date;
      });
    };
    
  • 3. adım: onları birleştirin

    [
        ...this.sortByDate(importantNotifications),
        ...this.sortByDate(unImportantNotifications),
      ];
    
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.