Dengan Backbone.js saya menyiapkan koleksi dengan fungsi komparator. Ini memilah model dengan baik, tetapi saya ingin membalik urutannya.
Bagaimana cara mengurutkan model dalam urutan turun daripada naik?
javascript
backbone.js
Drew Dara-Abrams
sumber
sumber
Jawaban:
Nah, Anda bisa mengembalikan nilai negatif dari pembanding. Jika kita ambil misalnya contoh dari situs Backbone dan ingin membalik urutannya, maka akan terlihat seperti ini:
var Chapter = Backbone.Model; var chapters = new Backbone.Collection; chapters.comparator = function(chapter) { return -chapter.get("page"); // Note the minus! }; chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"})); alert(chapters.pluck('title'));
sumber
Secara pribadi, saya tidak begitu senang dengan solusi yang diberikan di sini:
Solusi mengalikan dengan -1 gagal berfungsi jika jenis pengurutannya non-numerik. Meskipun ada cara untuk mengatasi ini (dengan menelepon
Date.getTime()
misalnya) kasus-kasus ini bersifat spesifik. Saya ingin cara umum untuk membalik arah apa pun, tanpa harus khawatir tentang jenis bidang tertentu yang sedang diurutkan.Untuk solusi string, membuat string satu karakter pada satu waktu tampak seperti hambatan kinerja, terutama saat menggunakan koleksi besar (atau memang, string bidang sortir besar)
Berikut solusi yang berfungsi dengan baik untuk bidang String, Tanggal dan Numerik:
Pertama, nyatakan pembanding yang akan membalikkan hasil dari fungsi sortBy, seperti ini:
function reverseSortBy(sortByFunction) { return function(left, right) { var l = sortByFunction(left); var r = sortByFunction(right); if (l === void 0) return -1; if (r === void 0) return 1; return l < r ? 1 : l > r ? -1 : 0; }; }
Sekarang, jika Anda ingin membalik arah pengurutan, yang perlu kita lakukan adalah:
var Chapter = Backbone.Model; var chapters = new Backbone.Collection; // Your normal sortBy function chapters.comparator = function(chapter) { return chapter.get("title"); }; // If you want to reverse the direction of the sort, apply // the reverseSortBy function. // Assuming the reverse flag is kept in a boolean var called reverseDirection if(reverseDirection) { chapters.comparator = reverseSortBy(chapters.comparator); } chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"})); alert(chapters.pluck('title'));
Alasan mengapa ini berfungsi adalah karena
Backbone.Collection.sort
berperilaku berbeda jika fungsi sortir memiliki dua argumen. Dalam hal ini, ia berperilaku dengan cara yang sama seperti pembanding yang diteruskanArray.sort
. Solusi ini bekerja dengan mengadaptasi fungsi sortBy argumen tunggal menjadi komparator dua argumen dan membalikkan hasilnya.sumber
Pembanding koleksi Backbone.js bergantung pada metode Underscore.js _.sortBy. Cara sortBy diimplementasikan berakhir dengan "membungkus" javascript .sort () dengan cara yang membuat pengurutan string secara terbalik menjadi sulit. Negasi sederhana dari string akhirnya mengembalikan NaN dan memutus pengurutan.
Jika Anda perlu melakukan pengurutan terbalik dengan String, seperti urutan abjad terbalik, berikut cara yang benar-benar hack untuk melakukannya:
comparator: function (Model) { var str = Model.get("name"); str = str.toLowerCase(); str = str.split(""); str = _.map(str, function(letter) { return String.fromCharCode(-(letter.charCodeAt(0))); }); return str; }
Ini tidak berarti cantik, tapi ini adalah "negator string". Jika Anda tidak ragu untuk mengubah jenis objek asli dalam javascript, Anda dapat membuat kode lebih jelas dengan mengekstrak negator string dan menambahkannya sebagai metode pada String.Prototype. Namun Anda mungkin hanya ingin melakukan ini jika Anda tahu apa yang Anda lakukan, karena memodifikasi jenis objek asli dalam javascript dapat menimbulkan konsekuensi yang tidak terduga.
sumber
Solusi saya adalah membalikkan hasil demi hasil.
Untuk mencegah rendering ganda, pertama urutkan dengan silent, lalu picu 'reset'.
collections.sort({silent:true}) collections.models = collections.models.reverse(); collections.trigger('reset', collections, {});
sumber
-Date.getTime()
, mungkin dengan beberapa peretasan tambahan jika Anda yakin tanggal di sistem Anda akan melewati zaman unix. Untuk alfabet, lihat jawaban Andrew di atas.Ubah fungsi komparator Anda untuk mengembalikan beberapa nilai proporisional terbalik alih-alih mengembalikan data Anda saat ini. Beberapa kode dari: http://documentcloud.github.com/backbone/#Collection-comparator
Contoh:
var Chapter = Backbone.Model; var chapters = new Backbone.Collection; /* Method 1: This sorts by page number */ chapters.comparator = function(chapter) { return chapter.get("page"); }; /* Method 2: This sorts by page number in reverse */ chapters.comparator = function(chapter) { return -chapter.get("page"); }; chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"}));
sumber
Berikut ini bekerja dengan baik untuk saya:
comparator: function(a, b) { // Optional call if you want case insensitive name1 = a.get('name').toLowerCase(); name2 = b.get('name').toLowerCase(); if name1 < name2 ret = -1; else if name1 > name2 ret = 1; else ret = 0; if this.sort_dir === "desc" ret = -ret return ret; } collection.sort_dir = "asc"; collection.sort(); // returns collection in ascending order collection.sort_dir = "desc"; collection.sort(); // returns collection in descending order
sumber
Saya membaca beberapa di mana fungsi komparator Backbone baik menggunakan atau meniru fungsi JavaScript Array.prototype.sort (). Artinya, model ini menggunakan 1, -1 atau 0 untuk menentukan urutan setiap model dalam koleksi. Ini terus diperbarui dan koleksi tetap dalam urutan yang benar berdasarkan pembanding.
Info tentang Array.prototype.sort () dapat ditemukan di sini: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript% 2FReferensi% 2FGlobal_Objects% 2FArray% 2Fsort
Banyak jawaban atas pertanyaan ini hanya membalik urutan sebelum membukanya ke halaman. Ini tidak ideal.
Menggunakan artikel di atas di Mozilla sebagai panduan, saya dapat menjaga koleksi saya diurutkan dalam urutan terbalik menggunakan kode berikut, kemudian kami cukup merender koleksi ke halaman dalam urutan saat ini dan kami dapat menggunakan bendera (reverseSortDirection) untuk membalik urutan .
//Assuming this or similar will be in your Backbone.Collection. sortKey: 'id', //The field name of the item in your collection reverseSortDirection: false, comparator: function(a, b) { var sampleDataA = a.get(this.sortKey), sampleDataB = b.get(this.sortKey); if (this.reverseSortDirection) { if (sampleDataA > sampleDataB) { return -1; } if (sampleDataB > sampleDataA) { return 1; } return 0; } else { if (sampleDataA < sampleDataB) { return -1; } if (sampleDataB < sampleDataA) { return 1; } return 0; } },
Pembanding, kecuali dua model, pada perubahan pada koleksi atau model, fungsi kompartor berjalan dan mengubah urutan koleksi.
Saya telah menguji pendekatan ini dengan Bilangan dan String dan tampaknya berhasil dengan sempurna untuk saya.
Saya sangat berharap jawaban ini dapat membantu karena saya telah berjuang dengan masalah ini berkali-kali dan biasanya berakhir dengan penyelesaian.
sumber
sortKey
danreverseSortDirection
dan memanggil.sort()
dari tampilan mana pun yang memiliki pegangan pada koleksi. Bagi saya, lebih sederhana daripada jawaban dengan suara terbanyak lainnya.Ini dapat dilakukan secara elegan dengan mengganti metode sortBy. Berikut ini contohnya
var SortedCollection = Backbone.Collection.extend({ initialize: function () { // Default sort field and direction this.sortField = "name"; this.sortDirection = "ASC"; }, setSortField: function (field, direction) { this.sortField = field; this.sortDirection = direction; }, comparator: function (m) { return m.get(this.sortField); }, // Overriding sortBy (copied from underscore and just swapping left and right for reverse sort) sortBy: function (iterator, context) { var obj = this.models, direction = this.sortDirection; return _.pluck(_.map(obj, function (value, index, list) { return { value: value, index: index, criteria: iterator.call(context, value, index, list) }; }).sort(function (left, right) { // swap a and b for reverse sort var a = direction === "ASC" ? left.criteria : right.criteria, b = direction === "ASC" ? right.criteria : left.criteria; if (a !== b) { if (a > b || a === void 0) return 1; if (a < b || b === void 0) return -1; } return left.index < right.index ? -1 : 1; }), 'value'); } });
Jadi Anda bisa menggunakannya seperti ini:
var collection = new SortedCollection([ { name: "Ida", age: 26 }, { name: "Tim", age: 5 }, { name: "Rob", age: 55 } ]); //sort by "age" asc collection.setSortField("age", "ASC"); collection.sort(); //sort by "age" desc collection.setSortField("age", "DESC"); collection.sort();
Solusi ini tidak bergantung pada jenis bidang.
sumber
// For numbers, dates, and other number-like things var things = new Backbone.Collection; things.comparator = function (a, b) { return b - a }; // For strings things.comparator = function (a, b) { if (a === b) return 0; return a < b ? -1 : 1; };
sumber
Berikut adalah solusi yang sangat sederhana, bagi mereka yang hanya ingin membalik pesanan saat ini. Ini berguna jika Anda memiliki tabel yang kolomnya dapat diurutkan dalam dua arah.
Anda dapat menggabungkannya dengan sesuatu seperti ini jika Anda tertarik dengan kasus tabel (coffeescript):
collection.comparator = (model) -> model.get(sortByType) collection.sort() if reverseOrder collection.models = collection.models.reverse()
sumber
Untuk urutan terbalik pada id:
comparator: function(object) { return (this.length - object.id) + 1; }
sumber
Saya memiliki persyaratan yang sedikit berbeda, yaitu saya menampilkan model saya dalam tabel, dan saya ingin dapat mengurutkannya berdasarkan kolom apa pun (properti model) dan menaik atau menurun.
Diperlukan waktu yang cukup lama untuk menyelesaikan semua kasus (di mana nilai dapat berupa string, string kosong, tanggal, angka. Namun saya pikir ini cukup dekat.
inverseString: function(str) { return str.split("").map(function (letter) { return String.fromCharCode(-(letter.charCodeAt(0))); }).join(""); } getComparisonValue: function (val, desc) { var v = 0; // Is a string if (typeof val === "string") { // Is an empty string, upgrade to a space to avoid strange ordering if(val.length === 0) { val = " "; return desc ? this.inverseString(val) : val; } // Is a (string) representing a number v = Number(val); if (!isNaN(v)) { return desc ? -1 * v : v; } // Is a (string) representing a date v = Date.parse(val); if (!isNaN(v)) { return desc ? -1 * v : v; } // Is just a string return desc ? this.inverseString(val) : val; } // Not a string else { return desc ? -1 * val : val; } },
menggunakan:
comparator: function (item) { // Store the collumn to 'sortby' in my global model var property = app.collections.global.get("sortby"); // Store the direction of the sorting also in the global model var desc = app.collections.global.get("direction") === "DESC"; // perform a comparison based on property & direction return this.getComparisonValue(item.get(property), desc); },
sumber
Saya baru saja mengesampingkan fungsi sortir untuk membalikkan larik model setelah selesai. Juga saya menahan memicu acara 'sort' sampai setelah kebalikannya selesai.
sort : function(options){ options = options || {}; Backbone.Collection.prototype.sort.call(this, {silent:true}); this.models.reverse(); if (!options.silent){ this.trigger('sort', this, options); } return this; },
sumber
Baru-baru ini mengalami masalah ini dan baru saja memutuskan untuk menambahkan metode rsort.
Collection = Backbone.Collection.extend({ comparator:function(a, b){ return a>b; }, rsort:function(){ var comparator = this.comparator; this.comparator = function(){ return -comparator.apply(this, arguments); } this.sort(); this.comparator = comparator; } });
Mudah-mudahan seseorang akan merasakan manfaatnya
sumber
Berikut adalah cara cepat dan mudah untuk menyortir ulang model koleksi menggunakan UnderscoreJS
var reverseCollection = _.sortBy(this.models, function(model) { return self.indexOf(model) * -1; });
sumber