Backbone.js के साथ क्रम को उल्टा करें


89

Backbone.js के साथ मैं एक संग्रह एक तुलनित्र समारोह के साथ स्थापित किया है। यह अच्छी तरह से मॉडल को छांट रहा है, लेकिन मैं आदेश को उलटना चाहूंगा।

मैं आरोही के बजाय अवरोही क्रम में मॉडल को कैसे सॉर्ट कर सकता हूं?


2
स्ट्रिंग्स (क्रिएट_ट फील्ड सहित) पर रिवर्स सॉर्टिंग के लिए, एक अन्य प्रश्न पर यह उत्तर देखें
— एरिक हू

2
2012 की शुरुआत के बाद से सॉर्ट-शैली तुलनित्रों के लिए समर्थन है। बस 2 तर्क स्वीकार करें और -1, 0 या 1. वापसी करें। github.com/documentcloud/backbone/commit/…
— geon

यह मेरे लिए काम किया है (स्ट्रिंग्स और नंबर): stackoverflow.com/questions/5013819/…
— FMD

जवाबों:


133

ठीक है, आप तुलनित्र से नकारात्मक मान लौटा सकते हैं। यदि हम, उदाहरण के लिए, बैकबोन की साइट से उदाहरण लेते हैं और ऑर्डर को उलटना चाहते हैं, तो यह इस तरह दिखेगा:

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

3
hi5 मेरा जैसा ही उदाहरण कोड का उपयोग करने के लिए! और 15 सेकंड के अंतर में। दिमाग की तरह मुझे कहना चाहिए
— ध्रुवपतक

ओह, निश्चित रूप से, सिर्फ एक माइनस साइन। आपकी त्वरित प्रतिक्रियाओं के लिए आप दोनों को धन्यवाद!
— ड्रू दारा-अब्राम्स

यह भी ध्यान दें कि (जैसा कि बैकबोन की साइट पर उल्लेख किया गया है) यह टूट जाता है यदि आप मॉडल के किसी भी विशेषता को बदलते हैं (यदि आप उदाहरण के लिए अध्याय में "लंबाई" विशेषता जोड़ते हैं)। उस स्थिति में आपको संग्रह पर "सॉर्ट ()" मैन्युअल रूप से कॉल करना होगा।
— cmcculloh

9
2012 की शुरुआत के बाद से सॉर्ट-शैली तुलनित्रों के लिए समर्थन है। बस 2 तर्क स्वीकार करें और -1, 0 या 1. वापसी करें। github.com/documentcloud/backbone/commit/…
— geon

@ फ़ासनी प्रतिक्रिया संख्याओं के अलावा अन्य प्रकारों के लिए काम करती है, कृपया एक नज़र डालें: stackoverflow.com/questions/5013819/…
— JayC

56

व्यक्तिगत रूप से, मैं यहां दिए गए किसी भी समाधान से खुश नहीं हूं:

  • -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। यह समाधान एकल तर्क सॉर्ट फ़ंक्शन को दो तर्क तुलनित्र में बदलने और परिणाम को उलट कर काम करता है।


7
जैसा कि इस सवाल का सबसे उत्कट जवाब देने वाला व्यक्ति है, मैं वास्तव में इस दृष्टिकोण को पसंद करता हूं और सोचता हूं कि इसमें अधिक उतार-चढ़ाव होना चाहिए।
— एंड्रयू डी एंड्रेड

बहुत बहुत धन्यवाद एंड्रयू
— एंड्रयू Newdigate

बहुत अच्छा, मैंने इसे थोड़ा सा ट्विक करना और बैकबोन में इसे अमूर्त करना शुरू कर दिया। बहुत बहुत धन्यवाद!
— केंड्रिक लेडेट

46

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 पर एक विधि के रूप में जोड़कर कोड को स्पष्ट कर सकते हैं। हालाँकि आप शायद केवल यह करना चाहते हैं यदि आप जानते हैं कि आप क्या कर रहे हैं, क्योंकि जावास्क्रिप्ट में मूल वस्तु प्रकारों को संशोधित करने के अप्रत्याशित परिणाम हो सकते हैं।


यह बहुत आसान है। धन्यवाद एंड्रयू!
— हाबिल

1
कोई परेशानी नहीं। मैं सिर्फ इतना जोड़ना चाहूंगा कि आपको अपने आप से पूछना चाहिए कि आप रिवर्स अल्फाबेटिकल प्रकार क्यों लागू कर रहे हैं और यदि उपयोगकर्ता अनुभव के दृष्टिकोण से शायद अधिक सुरुचिपूर्ण समाधान है।
— एंड्रयू डी एंड्रेड

1
@AndrewDeAndrade पर क्यों: मैं पहले 'सबसे नया' सेवा करके, 'create_at' विशेषता द्वारा एक संग्रह सॉर्ट करना चाहता हूं। यह विशेषता बैकबोन के डिफ़ॉल्ट लोगों में से एक है, और इसे स्ट्रिंग के रूप में संग्रहीत किया जाता है। मैं जो चाहता हूं, उसके करीब आपका जवाब आता है। धन्यवाद!
— एरिक हू

यह आश्चर्यजनक है, पिछले एक घंटे से इसके समाधान पर काम कर रहा है।

28

मेरा समाधान सॉर्ट के बाद परिणाम उल्टा करना था।

पहले रेंडर के साथ डबल रेंडरिंग को रोकने के लिए, फिर 'रीसेट' को ट्रिगर करें।

collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});

2
एक बेहतर समाधान यह है कि तुलनित्र के परिणाम को नकार दिया जाए।
— डेनियल एक्स मूर

7
डैनियल, यह हमेशा संभव नहीं होता है, उदाहरण के लिए जब स्ट्रिंग्स या डेट्स को सॉर्ट करना।
— गैविन शुल्ज़

1
यकीन से यही है। दिनांक के लिए आपके पास तुलनित्र रिटर्न हो -Date.getTime()सकता है, संभवतः कुछ अतिरिक्त हैकिंग के साथ यदि आपको लगता है कि आपके सिस्टम में तारीखें यूनिक्स युग को पार कर जाएंगी। वर्णमाला के लिए, ऊपर एंड्रयू के उत्तर को देखें।
— शतावरी

@DanielXMoore क्यों जरूरी है कि एक बेहतर समाधान? क्या यह तेज है? व्यक्तिगत रूप से मुझे उस विशेषता को संग्रहीत करना बहुत आसान लगता है जिसे उपयोगकर्ता ने पिछली बार संग्रह को सॉर्ट किया था, फिर वर्तमान सॉर्ट को उल्टा कर दें यदि वह फिर से उस विशेषता को सॉर्ट करता है; (आप एक विकिपीडिया तालिका में देखे जाने वाले सॉर्टिंग व्यवहार को लागू करने के लिए, जहां टेबल-हेडर में विशेषता को बार-बार क्लिक करके सॉर्ट-दिशा को टॉगल किया जा सकता है) इस तरह से मैं अपने तुलनित्र तर्क को साफ रखता हूं और अगर हम एस्कॉर्ट पर स्विच करते हैं तो खुद को एक सॉर्टिंग ऑपरेशन से बचा सकते हैं।
— डेस

13

वर्तमान में आपके द्वारा दिए गए डेटा को वापस करने के बजाए कुछ प्रतिवर्ती मूल्य वापस करने के लिए अपने तुलनित्र फ़ंक्शन को संशोधित करें। से कुछ कोड: 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"}));

9

निम्नलिखित ने मेरे लिए अच्छा काम किया:

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

8

मैंने कुछ पढ़ा कि बैकबोन तुलनित्र फ़ंक्शन या तो जावास्क्रिप्ट 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;
      }

},

कम्पैक्टर दो मॉडल को छोड़कर, संग्रह या मॉडल के परिवर्तन पर कम्पार्टर फ़ंक्शन चलाता है और संग्रह के क्रम को बदलता है।

मैंने नंबर और स्ट्रिंग्स के साथ इस दृष्टिकोण का परीक्षण किया है और ऐसा लगता है कि यह मेरे लिए पूरी तरह से काम कर रहा है।

मुझे वास्तव में उम्मीद है कि यह उत्तर मदद कर सकता है क्योंकि मैंने इस समस्या से कई बार संघर्ष किया है और आमतौर पर एक काम का उपयोग करके समाप्त होता है।


1
मुझे यह पसंद है क्योंकि तर्क संग्रह में रहता है, लेकिन आप आसानी से सेट कर सकते हैं sortKeyऔर किसी भी दृश्य से reverseSortDirectionकॉल कर सकते हैं, .sort()जो संग्रह पर एक हैंडल है। मेरे लिए अन्य उच्च-मतदान उत्तरों की तुलना में सरल।
— नूह हेल्डमैन

5

यह क्रमबद्ध तरीके से ओवरराइड करके किया जा सकता है। यहाँ एक उदाहरण है

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

यह समाधान फ़ील्ड प्रकार पर निर्भर नहीं करता है।


1
अच्छा था ! "शून्य 0" को "अपरिभाषित" द्वारा प्रतिस्थापित किया जा सकता है।
— GMO

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

2

यहाँ एक बहुत ही सरल उपाय है, उन लोगों के लिए जो केवल वर्तमान ऑर्डर को फ्लिप करना चाहते हैं। यह उपयोगी है यदि आपके पास एक तालिका है जिसके स्तंभों को दो दिशाओं में आदेश दिया जा सकता है।

collection.models = collection.models.reverse()

आप इसे कुछ इस तरह से जोड़ सकते हैं यदि आप तालिका मामले (कॉफ़ीस्क्रिप्ट) में रुचि रखते हैं:

  collection.comparator = (model) ->
    model.get(sortByType)

  collection.sort()

  if reverseOrder
    collection.models = collection.models.reverse()

2
इस स्थिति में, जब एक नया मॉडल संग्रह में जोड़ा जाता है, तो इसे सही ढंग से सॉर्ट नहीं किया जाएगा। जब से ।सेट विधि का उपयोग करके नए जोड़े गए मॉडल को क्रम में रखा जाता है, रिवर्सऑर्डर लागू होने से पहले परिणाम प्राप्त करें।
— फैबियो

1

आईडी पर रिवर्स ऑर्डर के लिए:

comparator: function(object) { return (this.length - object.id) + 1; }

0

मुझे थोड़ी अलग आवश्यकता थी, जिसमें मैं अपने मॉडलों को एक तालिका में प्रदर्शित कर रहा हूं, और मैं उन्हें किसी भी कॉलम (मॉडल संपत्ति) और या तो आरोही या अवरोही द्वारा क्रमबद्ध करना चाहता था।

इसने सभी मामलों को काम करने के लिए चारों ओर से बहुत अच्छी तरह से पिघला लिया है (जहां मान तार, खाली तार, दिनांक, संख्याएं हो सकते हैं। हालांकि मुझे लगता है कि यह बहुत करीब है।

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

0

मैं सिर्फ मॉडल सरणी को पूरा करने के लिए सॉर्ट फ़ंक्शन को ओवररोड करता हूं। इसके अलावा, जब तक रिवर्स पूरा नहीं हो जाता, तब तक मैं 'सॉर्ट' इवेंट को ट्रिगर करता रहा।

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

0

हाल ही में इस मुद्दे में भाग गया और बस एक 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;

            }
    });

उम्मीद है कि किसी को यह उपयोगी लगेगा


0

अंडरस्कोरजेस का उपयोग करके एक संग्रह के मॉडल को रिवर्स-सॉर्ट करने का एक त्वरित और आसान तरीका है

 var reverseCollection = _.sortBy(this.models, function(model) {
   return self.indexOf(model) * -1;
 });

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.