webentwicklung-frage-antwort-db.com.de

Sortierreihenfolge mit Backbone.js umkehren

Mit Backbone.js habe ich eine Sammlung mit einer Komparatorfunktion eingerichtet. Es ist schön, die Modelle zu sortieren, aber ich möchte die Reihenfolge umkehren.

Wie kann ich die Modelle in absteigender Reihenfolge anstatt in aufsteigender Reihenfolge sortieren?

89

Nun, Sie können negative Werte vom Komparator zurückgeben. Wenn wir zum Beispiel das Beispiel von der Backbone-Site nehmen und die Reihenfolge umkehren möchten, sieht es so aus:

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

Persönlich bin ich mit keiner der hier aufgeführten Lösungen so zufrieden:

  • Die Multiplikation mit -1 funktioniert nicht, wenn der Sortiertyp nicht numerisch ist. Obwohl es Möglichkeiten gibt, dies zu umgehen (z. B. durch Aufrufen von Date.getTime()), sind diese Fälle spezifisch. Ich möchte eine allgemeine Möglichkeit, die Richtung jeder Art umzukehren, ohne mich um den speziellen Typ des zu sortierenden Feldes kümmern zu müssen.

  • Für die String-Lösung scheint die Erstellung eines Strings Zeichen für Zeichen ein Leistungsengpass zu sein, insbesondere wenn große Auflistungen (oder sogar große Sortierfeld-Strings) verwendet werden.

Hier ist eine Lösung, die gut für Zeichenfolgen-, Datums- und numerische Felder funktioniert:

Deklarieren Sie zunächst einen Komparator, der das Ergebnis eines Ergebnisses einer sortBy-Funktion wie folgt umkehrt:

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

Wenn Sie nun die Richtung der Sortierung umkehren möchten, müssen wir nur Folgendes tun:

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

Der Grund dafür ist, dass Backbone.Collection.sort Sich anders verhält, wenn die Sortierfunktion zwei Argumente hat. In diesem Fall verhält es sich genauso wie der Komparator, der an Array.sort Übergeben wurde. Diese Lösung funktioniert, indem die sortBy-Funktion mit einem Argument in einen Komparator mit zwei Argumenten umgewandelt und das Ergebnis umgekehrt wird.

56

Der Auflistungsvergleich von Backbone.js basiert auf der Underscore.js-Methode _.sortBy. Die Art und Weise, wie sortBy implementiert wird, führt dazu, dass Javascript .sort () so "umbrochen" wird, dass das umgekehrte Sortieren von Zeichenfolgen erschwert wird. Eine einfache Negation der Zeichenfolge gibt NaN zurück und unterbricht die Sortierung.

Wenn Sie eine umgekehrte Sortierung mit Strings durchführen müssen, wie z. B. eine umgekehrte alphabetische Sortierung, ist dies eine wirklich hackige Methode:

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

Es ist keineswegs hübsch, aber es ist ein "String-Negator". Wenn Sie keine Bedenken haben, native Objekttypen in Javascript zu ändern, können Sie den Code klarer gestalten, indem Sie den String-Negator extrahieren und als Methode in String.Prototype hinzufügen. Allerdings möchten Sie dies wahrscheinlich nur tun, wenn Sie wissen, was Sie tun, da das Ändern der nativen Objekttypen in JavaScript unvorhergesehene Folgen haben kann.

46

Meine Lösung bestand darin, die Ergebnisse nach dem Sortieren umzukehren.

Um ein doppeltes Rendern zu verhindern, sortieren Sie zuerst mit silent und lösen Sie dann 'reset' aus.

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

Ändern Sie Ihre Komparatorfunktion, um einen Wert mit umgekehrtem Proportionalwert zurückzugeben, anstatt die Daten zurückzugeben, die Sie gerade sind. Code von: http://documentcloud.github.com/backbone/#Collection-comparator

Beispiel:

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"}));
13
DhruvPathak

Folgendes hat bei mir gut funktioniert:

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
9
rbhitchcock

Ich habe einige Beispiele gelesen, in denen die Backbone-Komparatorfunktion die JavaScript-Funktion Array.prototype.sort () verwendet oder imitiert. Dies bedeutet, dass entweder 1, -1 oder 0 verwendet wird, um die Sortierreihenfolge für jedes Modell in der Sammlung festzulegen. Dies wird ständig aktualisiert und die Sammlung bleibt in der richtigen Reihenfolge basierend auf dem Komparator.

Informationen zu Array.prototype.sort () finden Sie hier: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en- US & redirectslug = JavaScript% 2FReference% 2FGlobal_Objects% 2FArray% 2Fsort

Viele Antworten auf diese Frage kehren einfach die Reihenfolge um, bevor sie auf die Seite übertragen werden. Das ist nicht ideal.

Mit dem obigen Artikel über Mozilla als Leitfaden konnte ich meine Sammlung mit dem folgenden Code in umgekehrter Reihenfolge sortieren, dann rendern wir die Sammlung einfach in der aktuellen Reihenfolge und verwenden ein Flag (reverseSortDirection), um die Reihenfolge umzukehren .

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

},

Mit Ausnahme der beiden Modelle von Comparator wird bei Änderungen der Sammlung oder des Modells die Kompartimentfunktion ausgeführt und die Reihenfolge der Sammlung geändert.

Ich habe diesen Ansatz mit Numbers and Strings getestet und es scheint perfekt für mich zu funktionieren.

Ich hoffe wirklich, dass diese Antwort helfen kann, da ich mit diesem Problem viele Male gekämpft habe und normalerweise eine Umgehungslösung benutze.

8
Fasani

Dies kann elegant durch Überschreiben der sortBy-Methode erfolgen. Hier ist ein Beispiel

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

});

Du kannst es also so benutzen:

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

Diese Lösung hängt nicht vom Feldtyp ab.

5
Aman Mahajan
// 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;
};
3
wprl

Hier ist eine wirklich einfache Lösung für diejenigen, die einfach die aktuelle Reihenfolge umdrehen möchten. Es ist nützlich, wenn Sie eine Tabelle haben, deren Spalten in zwei Richtungen angeordnet werden können.

collection.models = collection.models.reverse()

Sie können es mit so etwas kombinieren, wenn Sie sich für den Tischkoffer (Coffeescript) interessieren:

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

  collection.sort()

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

Für umgekehrte Reihenfolge auf ID:

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

Ich hatte eine etwas andere Anforderung, da ich meine Modelle in einer Tabelle anzeige und sie nach einer beliebigen Spalte (Modelleigenschaft) und entweder aufsteigend oder absteigend sortieren wollte.

Es hat eine Menge Zeit gekostet, um alle Fälle zum Laufen zu bringen (wobei es sich bei den Werten um Zeichenfolgen, leere Zeichenfolgen, Datumsangaben und Zahlen handeln kann. Ich denke jedoch, dass dies ziemlich nahe ist.

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

verwenden:

    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
Josh Mc

Hier ist eine schnelle und einfache Möglichkeit, die Modelle einer Sammlung mithilfe von UnderscoreJS umzukehren

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

Ich bin kürzlich auf dieses Problem gestoßen und habe mich gerade entschlossen, eine Sortiermethode hinzuzufügen.

    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;

            }
    });

Hoffentlich findet das jemand nützlich

0
Diego Alejos

Ich habe gerade die Sortierfunktion überschrieben, um das Modellarray nach Fertigstellung umzukehren. Außerdem habe ich das 'sort'-Ereignis erst ausgelöst, nachdem der umgekehrte Vorgang abgeschlossen wurde.

    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
user2686693