İle backbone.js ben bıraktığım bir karşılaştırıcı işleviyle kurulmuş bir koleksiyonu var. Modelleri güzelce sıralıyor ama sırayı tersine çevirmek istiyorum.
Modelleri artan sırada değil, azalan sırada nasıl sıralayabilirim?
İle backbone.js ben bıraktığım bir karşılaştırıcı işleviyle kurulmuş bir koleksiyonu var. Modelleri güzelce sıralıyor ama sırayı tersine çevirmek istiyorum.
Modelleri artan sırada değil, azalan sırada nasıl sıralayabilirim?
Yanıtlar:
Peki, karşılaştırıcıdan negatif değerler döndürebilirsiniz. Örneğin Backbone'un sitesinden örnek alırsak ve sırayı tersine çevirmek istersek, şöyle görünecektir:
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'));
Şahsen, burada verilen çözümlerin hiçbirinden memnun değilim:
Sıralama türü sayısal olmadığında -1 ile çarpma çözümü çalışmaz. Bunun etrafından dolaşmanın yolları olsa da ( Date.getTime()örneğin arayarak ) bu vakalar özeldir. Sıralanan alanın belirli türü hakkında endişelenmek zorunda kalmadan, her türden yönü tersine çevirmenin genel bir yolunu istiyorum.
Dize çözümü için, her seferinde bir karakter dizesi oluşturmak, özellikle büyük koleksiyonlar (veya aslında, büyük sıralama alanı dizeleri) kullanırken bir performans darboğazı gibi görünüyor.
Dize, Tarih ve Sayısal alanlar için iyi çalışan bir çözüm:
İlk olarak, aşağıdaki gibi bir sortBy işlevinin sonucunu tersine çevirecek bir karşılaştırıcı bildirin:
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;
};
}
Şimdi, sıralamanın yönünü tersine çevirmek istiyorsanız, tek yapmamız gereken:
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'));
Bunun işe Backbone.Collection.sortyaramasının nedeni , sıralama işlevinin iki bağımsız değişkeni varsa farklı davranmasıdır. Bu durumda, karşılaştırıcının geçtiği gibi davranır Array.sort. Bu çözüm, tek bağımsız değişken sortBy işlevini iki bağımsız değişken karşılaştırıcısına uyarlayarak ve sonucu tersine çevirerek çalışır.
Backbone.js'nin koleksiyon karşılaştırıcısı, Underscore.js yöntemi _.sortBy'ye dayanır. SortBy'nin uygulanma biçimi, javascript .sort () dizgelerini tersine sıralamayı zorlaştıracak şekilde "sarmalar". Dizenin basit olumsuzlaması, NaN döndürür ve sıralamayı bozar.
Dizelerle ters alfabetik sıralama gibi bir ters sıralama yapmanız gerekiyorsa, işte bunu yapmanın gerçekten hilekâr bir yolu:
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;
}
Hiç de güzel değil, ama bir "dizi olumsuzlayıcı". JavaScript'te yerel nesne türlerini değiştirmeye yönelik herhangi bir niteliğiniz yoksa, string negator'ı ayıklayıp String.Prototype üzerine bir yöntem olarak ekleyerek kodu daha net hale getirebilirsiniz. Bununla birlikte, muhtemelen yalnızca ne yaptığınızı biliyorsanız bunu yapmak istersiniz, çünkü javascript'te yerel nesne türlerini değiştirmenin öngörülemeyen sonuçları olabilir.
Benim çözümüm, sonuçları sıralamadan sonra tersine çevirmekti.
Çift oluşturmayı önlemek için önce sessiz olarak sıralayın, ardından 'sıfırla'yı tetikleyin.
collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});
-Date.getTime()için, sisteminizdeki tarihlerin unix çağını geçeceğine inanıyorsanız, muhtemelen fazladan bir hackleme ile karşılaştırıcının geri dönmesini sağlayabilirsiniz . Alfabetik olarak, Andrew'un yukarıdaki cevabına bakın.
Karşılaştırıcı işlevinizi, şu anda bulunduğunuz verileri döndürmek yerine ters orantılı bir değer döndürmek için değiştirin. Bazı kodlar: http://documentcloud.github.com/backbone/#Collection-comparator
Misal:
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"}));
Aşağıdakiler benim için iyi çalıştı:
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
Backbone karşılaştırıcı işlevinin JavaScript Array.prototype.sort () işlevini kullandığı veya taklit ettiği bazı yerlerde okudum. Bu, koleksiyondaki her modelin sıralama düzenine karar vermek için 1, -1 veya 0 kullandığı anlamına gelir. Bu sürekli olarak güncellenir ve koleksiyon, karşılaştırıcıya göre doğru sırada kalır.
Array.prototype.sort () ile ilgili bilgiler burada bulunabilir: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript% 2FReference% 2FGlobal_Objects% 2FArray% 2Fsort
Bu soruya verilen pek çok cevap, sayfaya dönmeden hemen önce sırayı tersine çevirir. Bu ideal değil.
Mozilla ile ilgili yukarıdaki makaleyi bir kılavuz olarak kullanarak, koleksiyonumu aşağıdaki kodu kullanarak ters sırada sıralı tutabildim, sonra koleksiyonu mevcut sırasına göre sayfaya dönüştürdük ve sıralamayı tersine çevirmek için bir bayrak (reverseSortDirection) kullanabiliriz .
//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;
}
},
Karşılaştırıcı, iki model hariç, koleksiyon veya modelde yapılan değişikliklerde karşılaştırma işlevi çalışır ve koleksiyonun sırasını değiştirir.
Bu yaklaşımı Numbers and Strings ile test ettim ve benim için mükemmel çalışıyor gibi görünüyor.
Bu sorunla birçok kez mücadele ettiğim ve genellikle bir çalışma kullanmamla sonuçlandığım için bu cevabın yardımcı olabileceğini umuyorum.
sortKeyve reverseSortDirectionaramayı ve .sort()koleksiyon ile ilgilenecek herhangi bir görünümden. Benim için diğer yüksek oy alan cevaplardan daha basit.
Bu, sortBy yöntemini geçersiz kılarak zarif bir şekilde yapılabilir. İşte bir örnek
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');
}
});
Yani bunu şu şekilde kullanabilirsiniz:
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();
Bu çözüm, alan türüne bağlı değildir.
İşte sadece mevcut sırayı tersine çevirmek isteyenler için gerçekten basit bir çözüm. Sütunları iki yönde sıralanabilen bir tablonuz varsa kullanışlıdır.
collection.models = collection.models.reverse()
Masa örneğiyle ilgileniyorsanız, bunu aşağıdaki gibi bir şeyle birleştirebilirsiniz (kahve yazı)
collection.comparator = (model) ->
model.get(sortByType)
collection.sort()
if reverseOrder
collection.models = collection.models.reverse()
Modellerimi bir tabloda görüntülediğim için biraz farklı bir gereksinimim vardı ve bunları herhangi bir collumn (model özelliği) ile ya artan ya da azalan şekilde sıralayabilmek istedim.
Tüm vakaların (değerlerin dizeler, boş dizeler, tarihler, sayılar olabileceği yerlerde) çalışabilmesi için oldukça fazla uğraşmak gerekti. Ancak bence bu oldukça yakın.
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;
}
},
kullanım:
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);
},
Tamamlandıktan sonra modeller dizisini tersine çevirmek için sıralama işlevini geçersiz kıldım. Ayrıca, tersi tamamlanana kadar 'sıralama' olayını tetiklemeyi bıraktım.
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;
},
Son zamanlarda bu sorunla karşılaştı ve bir rsort yöntemi eklemeye karar verdim.
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;
}
});
Umarım birisi bunu faydalı bulacaktır
UnderscoreJS kullanarak bir koleksiyonun modellerini ters sıralamak için hızlı ve kolay bir yol.
var reverseCollection = _.sortBy(this.models, function(model) {
return self.indexOf(model) * -1;
});