Bagaimana saya bisa melakukan semacam asc dan desc menggunakan underscore.js?

166

Saat ini saya menggunakan underscorejs untuk mengurutkan json sorting saya. Sekarang saya telah diminta untuk melakukan ascendingdan descendingmenyortir menggunakan underscore.js. Saya tidak melihat apa pun mengenai hal yang sama dalam dokumentasi. Bagaimana saya bisa mencapai ini?

Rahul
sumber
1
Silakan tambahkan contoh apa yang Anda sortir dan caranya.
Jon
Apa yang kamu sortir? Angka? String? Tanggal? Sesuatu yang lain
mu terlalu pendek
@muistooshort Saya menyortir berbagai objek. Jadi metode sortBy cocok dengan kriteria saya dengan sempurna untuk urutan naik tetapi tidak sebaliknya.
Rahul
Jika Anda mengurutkan berdasarkan angka maka sortByfungsi Anda bisa return -ntetapi itu tidak akan berfungsi untuk string; maka dari itu pertanyaan tentang hal-hal seperti apa yang Anda sortir.
mu terlalu pendek
2
Dengan Lodash Anda dapat menggunakan steno suka _.sortBy([1,4,3,2]).reverse()atau _.chain([1,4,3,2]).sortBy().reverse().value()jika Anda tidak ingin menggunakan reverse()prototipe Array.
GFoley83

Jawaban:

363

Anda dapat menggunakan .sortBy, itu akan selalu mengembalikan daftar naik :

_.sortBy([2, 3, 1], function(num) {
    return num;
}); // [1, 2, 3]

Tetapi Anda dapat menggunakan metode .reverse untuk mendapatkannya turun :

var array = _.sortBy([2, 3, 1], function(num) {
    return num;
});

console.log(array); // [1, 2, 3]
console.log(array.reverse()); // [3, 2, 1]

Atau ketika berhadapan dengan angka, tambahkan tanda negatif ke kembalinya ke daftar:

_.sortBy([-3, -2, 2, 3, 1, 0, -1], function(num) {
    return -num;
}); // [3, 2, 1, 0, -1, -2, -3]

Di bawah kap .sortBymenggunakan built in .sort([handler]):

// Default is ascending:
[2, 3, 1].sort(); // [1, 2, 3]

// But can be descending if you provide a sort handler:
[2, 3, 1].sort(function(a, b) {
    // a = current item in array
    // b = next item in array
    return b - a;
});
andlrc
sumber
9
Solusi terakhir yaitu menambahkan tanda negatif ke num yang dikembalikan adalah sempurna.
vinesh
Mengapa Anda berpikir itu semacam gelembung? Di bawah kap .sortBy()panggilan built-in Array.sort(), algoritma yang terserah vendor browser, tetapi semacam gelembung sangat tidak mungkin menjadi pilihan mereka.
Rene Saarsoo
Bukankah ini meningkatkan kompleksitas waktu? Itu menyebabkan daftar harus diurutkan dua kali.
user1477388
@ user1477388 Saya tidak yakin apa yang Anda maksud tentang diurutkan dua kali?
andlrc
@andlrc Jadi, ketika Anda menelepon _.sortBy(arr, function), saya menganggap itu loop atas setiap item dan menjalankan beberapa logika untuk mengembalikan array yang diurutkan. Kemudian, ketika Anda menyebutnya Array.prototype.reverse()mungkin mengulangi setiap item lagi dan menjalankan beberapa logika untuk mengembalikan array yang terbalik. Oleh karena itu, Anda mengulang array dua kali.
user1477388
57

Urutan menurun menggunakan garis bawah dapat dilakukan dengan mengalikan nilai kembali dengan -1.

//Ascending Order:
_.sortBy([2, 3, 1], function(num){
    return num;
}); // [1, 2, 3]


//Descending Order:
_.sortBy([2, 3, 1], function(num){
    return num * -1;
}); // [3, 2, 1]

Jika Anda mengurutkan berdasarkan string bukan angka, Anda dapat menggunakan metode charCodeAt () untuk mendapatkan nilai unicode.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});
jEremyB
sumber
3
Saya mencoba mengurutkan berdasarkan abjad - mengalikan dengan -1 bukanlah operasi yang valid. :)
rythos42
Nilainya saat digunakan tetapi tidak ditentukan dalam pertanyaan. Namun, mengalikan string dengan -1 adalah operasi yang valid. Ini mengembalikan NaN, yang merupakan hasil yang valid.
jEremyB
1
ingat untuk menetapkan kembali array juga! SOME_ARR = _.sortBy (SOME_ARR, function (num) {SOME_FUNC ...});
aqm
4
charCodeAt akan "mengembalikan Unicode karakter pada indeks yang ditentukan dalam string" sehingga dapat digunakan untuk mengurutkan berdasarkan karakter dalam string, tetapi seperti yang ditunjukkan itu tidak "urutkan berdasarkan string" itu mengurutkan berdasarkan karakter dalam string
Anthony
2
Ini hanya mengurutkan berdasarkan karakter pertama, dan case case sensitive.
Aidan
50

The Array prototipe metode sebaliknya memodifikasi array dan kembali referensi untuk itu, yang berarti Anda dapat melakukan ini:

var sortedAsc = _.sortBy(collection, 'propertyName');
var sortedDesc = _.sortBy(collection, 'propertyName').reverse();

Juga, dokumentasi garis bawah berbunyi:

Selain itu, metode prototipe Array diproksikan melalui objek Garis Bawah dirantai, sehingga Anda dapat memasukkan a reverseatau a pushke dalam rantai Anda, dan terus memodifikasi array.

yang berarti Anda juga dapat menggunakan .reverse()saat merantai:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();
Emil Lundberg
sumber
Ini adalah dengan cara metode paling sederhana untuk penyortiran terbalik / menurun ketika datang ke kasus penggunaan paling sederhana.
Dan Atkinson
2
Untuk melakukan jenis abjad yang tidak peka huruf besar-kecil:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -
ini tidak berfungsi jika ada angka negatif dalam array.
Shruti Kapoor
@ShrutiKapoor Ya itu. Kenapa tidak?
Emil Lundberg
5
Dari segi kinerja, akan lebih baik untuk menerapkan filter terlebih dahulu dan kemudian mengurutkan nilai (yang tersisa).
Saran
12

Mirip dengan Underscore library ada perpustakaan lain yang disebut sebagai 'lodash' yang memiliki satu metode "orderBy" yang mengambil parameter untuk menentukan di mana urutan untuk mengurutkannya. Anda bisa menggunakannya seperti

_.orderBy('collection', 'propertyName', 'desc')

Untuk beberapa alasan, itu tidak didokumentasikan pada dokumen situs web.

Minkesh Jain
sumber
Saya pikir Anda bingung menggarisbawahi dengan lodash . Hanya yang terakhir memiliki fungsi orderBy yang disebutkan .
Thomas Marti
Ya, salahku. Akan memperbarui jawabannya. Terima kasih telah mengoreksi :)
Minkesh Jain
orderBy, sangat berguna! Jauh lebih baik daripada menggunakan reverse, karena mempertahankan properti sortir stabil yang saya cari.
Flimm
Tidak bekerja untuk saya untuk beberapa alasan upadte: itu lodash (
aleXela
0

Garis Bawah Garis Bawah

Memperluas jawaban @ emil_lundberg, Anda juga dapat menulis "mixin" jika Anda menggunakan Underscore untuk membuat fungsi kustom untuk mengurutkan jika itu semacam pengurutan yang mungkin Anda ulangi dalam aplikasi di suatu tempat.

Misalnya, mungkin Anda memiliki pengontrol atau melihat hasil pengurutan dengan urutan pengurutan "ASC" atau "DESC", dan Anda ingin beralih di antara jenis itu, Anda bisa melakukan sesuatu seperti ini:

Mixin.js

_.mixin({
    sortByOrder: function(stooges, prop, order) {
      if (String(order) === "desc") {
          return _.sortBy(stooges, prop).reverse();
      } else if (String(order) === "asc") {
          return _.sortBy(stooges, prop);
      } else {
          return stooges;
      }
    }
})

Contoh Penggunaan

var sort_order = "asc";
var stooges = [
  {name: 'moe', age: 40}, 
  {name: 'larry', age: 50}, 
  {name: 'curly', age: 60},
  {name: 'July', age: 35},
  {name: 'mel', age: 38}
 ];

_.mixin({
    sortByOrder: function(stooges, prop, order) {
    if (String(order) === "desc") {
        return _.sortBy(stooges, prop).reverse();
    } else if (String(order) === "asc") {
        return _.sortBy(stooges, prop);
    } else {
        return stooges;
    }
  }
})


// find elements
var banner = $("#banner-message");
var sort_name_btn = $("button.sort-name");
var sort_age_btn = $("button.sort-age");

function showSortedResults(results, sort_order, prop) {
    banner.empty();
    banner.append("<p>Sorting: " + prop + ', ' + sort_order + "</p><hr>")
  _.each(results, function(r) {
    banner.append('<li>' + r.name + ' is '+ r.age + ' years old.</li>');
  }) 
}

// handle click and add class
sort_name_btn.on("click", function() {
  sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'name', sort_order);
  showSortedResults(sortedResults, sort_order, 'name');
})

sort_age_btn.on('click', function() {
    sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'age', sort_order);
  showSortedResults(sortedResults, sort_order, 'age');
})

Inilah JSFiddle yang menunjukkan ini: JSFiddle untuk SortBy Mixin

RoboBear
sumber