Array sortir Javascript dengan dua bidang


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

Jadi kode di atas mengurutkan array dengan gsize - dari terkecil ke terbesar. Ini bekerja dengan baik. Tetapi jika ukuran gsize sama, saya ingin mengurutkan berdasarkan cahaya.

Terima kasih.


fungsi sortir bereaksi pada hasil positif, negatif atau nol. jadi Anda bisa menulis: "return aSize - bSize". itu akan menjadi kode yang lebih sederhana dan mudah dibaca.

Jawaban:


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

Untuk membuat lebih ringkas ini menggunakan panah sintaks, tanpa menggunakan teknik non-jelas ditunjukkan dalam beberapa jawaban lain: grouperArray.sort((a, b) => a.gsize == b.gsize ? a.glow - b.glow : a.gsize - b.gsize. Untuk membuat kode lebih mudah dipahami, kami terus menguji secara eksplisit ==.
ToolmakerSteve

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

versi yang lebih pendek


jalan pintas yang bagus! membantu saya menyusun solusi yang lebih kompleks bersama .. stackoverflow.com/questions/6101475/…
Joseph Poirier

3
Bagus dan bersih! Satu-satunya hal itu hanya berfungsi untuk angka.
Afanasii Kurakin

Bisakah Anda menjelaskan logikanya di sini?!. Ini berhasil bagi saya sort an array with a key's value firstdan kemudiansort the result with another key's value
KTM

1
@KTM Logikanya adalah sebagai berikut: jika kedua gsize sama, maka bagian pertama dari kondisi tersebut sama dengan 0, yang dianggap salah, dan bagian kedua dari ketentuan tersebut dijalankan.
Scalpweb

@Scalpweb Ya :) jadi ini berfungsi untuk mengurutkan array dengan sejumlah kunci satu per satu kan ?! Trik bagus
KTM


14

Saya menyadari ini telah ditanyakan beberapa waktu lalu, tetapi saya pikir saya akan menambahkan solusi saya.

Fungsi ini menghasilkan metode pengurutan secara dinamis. cukup berikan setiap nama properti turunan yang dapat diurutkan, diawali dengan +/- untuk menunjukkan urutan naik atau turun. Sangat dapat digunakan kembali, dan tidak perlu mengetahui apa pun tentang struktur data yang telah Anda susun. Bisa dibuat bukti bodoh - tapi sepertinya tidak perlu.

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

contoh penggunaan:

items.sort (getSortMethod ('- price', '+ priority', '+ name'));

ini akan mengurutkan itemsdengan yang terendah priceterlebih dahulu, dengan ikatan menuju ke item dengan yang tertinggi priority. ikatan selanjutnya diputus oleh item tersebutname

dimana item adalah array seperti:

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

demo langsung: http://gregtaff.com/misc/multi_field_sort/

EDIT: Memperbaiki masalah Chrome.


Ini brilian
Azure

Jawaban jenius!
Marius

untuk skrip ketikan (untuk tidak mendapatkan error TS2554: Expected 0 arguments, but got ..) gunakan sintaks di sini: stackoverflow.com/a/4116634/5287221
Chananel P

6

Saya berharap operator terner((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;) membuat Anda bingung. Anda harus memeriksa tautan untuk memahaminya dengan lebih baik.

Sampai saat itu, berikut kode Anda meledak menjadi penuh if / else.

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

Berikut adalah implementasi untuk mereka yang mungkin menginginkan sesuatu yang lebih umum yang akan bekerja dengan sejumlah bidang.

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

}

Pada dasarnya, Anda dapat menentukan sejumlah nama properti / arah pengurutan:

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

Berikut adalah implementasi yang menggunakan rekursi untuk mengurutkan berdasarkan sejumlah bidang pengurutan dari 1 hingga tak terbatas. Anda memberikan larik hasil yang merupakan larik objek hasil untuk diurutkan, dan larik sortir yang merupakan larik objek pengurutan yang mendefinisikan pengurutan. Setiap objek pengurutan harus memiliki kunci "pilih" untuk nama kunci yang diurutkan dan kunci "urutan" yang berupa string yang menunjukkan "naik" atau "turun".

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

Cara dinamis untuk melakukannya dengan tombol GANDA:

  • memfilter nilai unik dari setiap kolom / kunci pengurutan
  • mengatur atau membalikkannya
  • menambahkan bobot zeropad lebar untuk setiap objek berdasarkan nilai kunci indexOf (nilai)
  • mengurutkan menggunakan bobot caclutated

masukkan deskripsi gambar di sini

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

Menggunakan:

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

masukkan deskripsi gambar di sini


1

Ini yang saya gunakan

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

menggabungkan dua item sebagai string dan mereka akan diurutkan berdasarkan nilai string. Jika mau, Anda dapat membungkus _a dan _b dengan parseInt untuk membandingkannya sebagai angka jika Anda tahu bahwa keduanya akan berupa angka.


1

Berikut adalah solusi untuk kasus ini, saat Anda memiliki kunci pengurutan prioritas, yang mungkin tidak ada di beberapa item tertentu, jadi Anda harus mengurutkan berdasarkan kunci cadangan.

Contoh data masukan ( id2 adalah kunci sortir prioritas):

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

Dan hasilnya harus:

[ { 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 } ]

Fungsi pembandingnya akan seperti:

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

PS Dalam kasus jika .id dari .id2 bisa nol, pertimbangkan untuk menggunakan 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;
});

belum diuji, tapi saya pikir itu seharusnya berhasil.


0

Dalam kasus saya, saya mengurutkan daftar pemberitahuan berdasarkan param 'penting' dan menurut 'tanggal'

  • langkah 1: saya memfilter pemberitahuan dengan 'penting' dan tidak penting

    let importantNotifications = notifications.filter(
            (notification) => notification.isImportant);
    
      let unImportantNotifications = notifications.filter(
            (notification) => !notification.isImportant);
    
  • langkah 2: saya mengurutkannya berdasarkan tanggal

      sortByDate = (notifications) => {
      return notifications.sort((notificationOne, notificationTwo) => {
        return notificationOne.date - notificationTwo.date;
      });
    };
    
  • langkah 3: gabungkan mereka

    [
        ...this.sortByDate(importantNotifications),
        ...this.sortByDate(unImportantNotifications),
      ];
    
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.