Backbone.js के साथ मैं एक संग्रह एक तुलनित्र समारोह के साथ स्थापित किया है। यह अच्छी तरह से मॉडल को छांट रहा है, लेकिन मैं आदेश को उलटना चाहूंगा।
मैं आरोही के बजाय अवरोही क्रम में मॉडल को कैसे सॉर्ट कर सकता हूं?
Backbone.js के साथ मैं एक संग्रह एक तुलनित्र समारोह के साथ स्थापित किया है। यह अच्छी तरह से मॉडल को छांट रहा है, लेकिन मैं आदेश को उलटना चाहूंगा।
मैं आरोही के बजाय अवरोही क्रम में मॉडल को कैसे सॉर्ट कर सकता हूं?
जवाबों:
ठीक है, आप तुलनित्र से नकारात्मक मान लौटा सकते हैं। यदि हम, उदाहरण के लिए, बैकबोन की साइट से उदाहरण लेते हैं और ऑर्डर को उलटना चाहते हैं, तो यह इस तरह दिखेगा:
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'));
व्यक्तिगत रूप से, मैं यहां दिए गए किसी भी समाधान से खुश नहीं हूं:
-1 प्रकार से गुणा करने पर यह काम करने में विफल रहता है जब सॉर्ट प्रकार गैर-संख्यात्मक होता है। हालाँकि इसके चारों ओर तरीके हैं ( Date.getTime()उदाहरण के लिए कॉल करके ) ये मामले विशिष्ट हैं। मैं किसी भी प्रकार की दिशा को उलटने का एक सामान्य तरीका चाहूंगा, बिना किसी विशेष प्रकार के क्षेत्र के बारे में चिंता किए बिना।
स्ट्रिंग समाधान के लिए, एक बार में एक स्ट्रिंग एक चरित्र का निर्माण एक प्रदर्शन अड़चन की तरह लगता है, खासकर जब बड़े संग्रह (या वास्तव में, बड़े सॉर्ट फ़ील्ड स्ट्रिंग्स) का उपयोग करते हुए
यहाँ एक समाधान है जो स्ट्रिंग, दिनांक और संख्यात्मक क्षेत्रों के लिए अच्छी तरह से काम करता है:
सबसे पहले, एक तुलनित्र की घोषणा करें, जो इस तरह के एक सॉर्ट फ़ंक्शन के परिणाम को उल्टा कर देगा:
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;
};
}
अब, यदि आप सॉर्ट की दिशा को उलटना चाहते हैं, तो हमें केवल इतना करना होगा:
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'));
कारण यह है कि Backbone.Collection.sortयदि सॉर्ट फ़ंक्शन में दो तर्क हैं, तो यह अलग तरह से व्यवहार करता है । इस मामले में, यह उसी तरह से व्यवहार करता है जैसे कि तुलनित्र पास हुआ Array.sort। यह समाधान एकल तर्क सॉर्ट फ़ंक्शन को दो तर्क तुलनित्र में बदलने और परिणाम को उलट कर काम करता है।
Backbone.js का संग्रह तुलनित्र Underscore.js विधि _.sortBy पर निर्भर करता है। जिस तरह से छंटनी की जाती है, वह जावास्क्रिप्ट (।) को एक तरह से "रैपिंग" करता है, जो उल्टे मुश्किल में छंटाई करता है। स्ट्रिंग का सरल नकार एनएएन लौटाने को समाप्त करता है और सॉर्ट को तोड़ता है।
यदि आपको स्ट्रिंग्स के साथ एक रिवर्स सॉर्ट करने की आवश्यकता है, जैसे कि रिवर्स अल्फाबेटिकल सॉर्ट, यहां यह करने का वास्तव में हैकिश तरीका है:
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;
}
यह किसी भी तरह से सुंदर नहीं है, लेकिन यह एक "स्ट्रिंग निगेटर" है। यदि आपके पास जावास्क्रिप्ट में मूल वस्तु प्रकारों को संशोधित करने के साथ कोई योग्यता नहीं है, तो आप स्ट्रिंग नेगेटर को निकालकर और इसे String.Prototype पर एक विधि के रूप में जोड़कर कोड को स्पष्ट कर सकते हैं। हालाँकि आप शायद केवल यह करना चाहते हैं यदि आप जानते हैं कि आप क्या कर रहे हैं, क्योंकि जावास्क्रिप्ट में मूल वस्तु प्रकारों को संशोधित करने के अप्रत्याशित परिणाम हो सकते हैं।
मेरा समाधान सॉर्ट के बाद परिणाम उल्टा करना था।
पहले रेंडर के साथ डबल रेंडरिंग को रोकने के लिए, फिर 'रीसेट' को ट्रिगर करें।
collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});
-Date.getTime()सकता है, संभवतः कुछ अतिरिक्त हैकिंग के साथ यदि आपको लगता है कि आपके सिस्टम में तारीखें यूनिक्स युग को पार कर जाएंगी। वर्णमाला के लिए, ऊपर एंड्रयू के उत्तर को देखें।
वर्तमान में आपके द्वारा दिए गए डेटा को वापस करने के बजाए कुछ प्रतिवर्ती मूल्य वापस करने के लिए अपने तुलनित्र फ़ंक्शन को संशोधित करें। से कुछ कोड: http://documentcloud.github.com/backbone/#Collection-comparator
उदाहरण:
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"}));
निम्नलिखित ने मेरे लिए अच्छा काम किया:
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
मैंने कुछ पढ़ा कि बैकबोन तुलनित्र फ़ंक्शन या तो जावास्क्रिप्ट Array.prototype.sort () फ़ंक्शन का उपयोग करता है या नकल करता है। इसका मतलब है कि यह संग्रह में प्रत्येक मॉडल के क्रम को तय करने के लिए 1, -1 या 0 का उपयोग करता है। यह लगातार अद्यतन करता है और संग्रह तुलनित्र के आधार पर सही क्रम में रहता है।
Array.prototyp.sort () पर जानकारी यहां पाई जा सकती है: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array-sort?redirectlocale=en-US&redirectslug=JavaScript% 2FReference% 2FGlobal_Objects% 2FArray% 2Fsort
इस प्रश्न के कई उत्तर पृष्ठ पर भेजने से ठीक पहले आदेश को उल्टा कर देते हैं। यह आदर्श नहीं है।
मोजिला पर उपर्युक्त लेख का उपयोग एक गाइड के रूप में कर रहा हूं, ताकि मैं निम्नलिखित कोड का उपयोग करके अपने संग्रह को रिवर्स ऑर्डर में क्रमबद्ध रख सकूं, फिर हम केवल संग्रह को वर्तमान क्रम में पेज पर रेंडर कर देते हैं और ऑर्डर को उलटने के लिए हम एक ध्वज (रिवर्ससॉर्टडायरेक्शन) का उपयोग कर सकते हैं ।
//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;
}
},
कम्पैक्टर दो मॉडल को छोड़कर, संग्रह या मॉडल के परिवर्तन पर कम्पार्टर फ़ंक्शन चलाता है और संग्रह के क्रम को बदलता है।
मैंने नंबर और स्ट्रिंग्स के साथ इस दृष्टिकोण का परीक्षण किया है और ऐसा लगता है कि यह मेरे लिए पूरी तरह से काम कर रहा है।
मुझे वास्तव में उम्मीद है कि यह उत्तर मदद कर सकता है क्योंकि मैंने इस समस्या से कई बार संघर्ष किया है और आमतौर पर एक काम का उपयोग करके समाप्त होता है।
sortKeyऔर किसी भी दृश्य से reverseSortDirectionकॉल कर सकते हैं, .sort()जो संग्रह पर एक हैंडल है। मेरे लिए अन्य उच्च-मतदान उत्तरों की तुलना में सरल।
यह क्रमबद्ध तरीके से ओवरराइड करके किया जा सकता है। यहाँ एक उदाहरण है
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');
}
});
तो आप इसे इस तरह से उपयोग कर सकते हैं:
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();
यह समाधान फ़ील्ड प्रकार पर निर्भर नहीं करता है।
यहाँ एक बहुत ही सरल उपाय है, उन लोगों के लिए जो केवल वर्तमान ऑर्डर को फ्लिप करना चाहते हैं। यह उपयोगी है यदि आपके पास एक तालिका है जिसके स्तंभों को दो दिशाओं में आदेश दिया जा सकता है।
collection.models = collection.models.reverse()
आप इसे कुछ इस तरह से जोड़ सकते हैं यदि आप तालिका मामले (कॉफ़ीस्क्रिप्ट) में रुचि रखते हैं:
collection.comparator = (model) ->
model.get(sortByType)
collection.sort()
if reverseOrder
collection.models = collection.models.reverse()
मुझे थोड़ी अलग आवश्यकता थी, जिसमें मैं अपने मॉडलों को एक तालिका में प्रदर्शित कर रहा हूं, और मैं उन्हें किसी भी कॉलम (मॉडल संपत्ति) और या तो आरोही या अवरोही द्वारा क्रमबद्ध करना चाहता था।
इसने सभी मामलों को काम करने के लिए चारों ओर से बहुत अच्छी तरह से पिघला लिया है (जहां मान तार, खाली तार, दिनांक, संख्याएं हो सकते हैं। हालांकि मुझे लगता है कि यह बहुत करीब है।
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;
}
},
उपयोग:
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);
},
मैं सिर्फ मॉडल सरणी को पूरा करने के लिए सॉर्ट फ़ंक्शन को ओवररोड करता हूं। इसके अलावा, जब तक रिवर्स पूरा नहीं हो जाता, तब तक मैं 'सॉर्ट' इवेंट को ट्रिगर करता रहा।
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;
},
हाल ही में इस मुद्दे में भाग गया और बस एक 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;
}
});
उम्मीद है कि किसी को यह उपयोगी लगेगा
अंडरस्कोरजेस का उपयोग करके एक संग्रह के मॉडल को रिवर्स-सॉर्ट करने का एक त्वरित और आसान तरीका है
var reverseCollection = _.sortBy(this.models, function(model) {
return self.indexOf(model) * -1;
});