[Javascript] Umgekehrte Sortierreihenfolge mit Backbone.js


Answers

Persönlich bin ich nicht glücklich mit den hier gegebenen Lösungen:

  • Die Multiplikation mit -1 Lösung funktioniert nicht, wenn der Sortierungstyp nicht numerisch ist. Es gibt zwar Möglichkeiten Date.getTime() z. B. durch Aufrufen von Date.getTime() ), diese Fälle sind jedoch spezifisch. Ich möchte einen allgemeinen Weg, um die Richtung jeder Art umzukehren, ohne sich um den speziellen Typ des Feldes kümmern zu müssen, das sortiert wird.

  • Für die String-Lösung ist das Konstruieren eines Strings um jeweils ein Zeichen ein Leistungsengpass, besonders bei großen Sammlungen (oder großen Sortierfeldfolgen).

Hier ist eine Lösung, die für String, Date und Numeric Felder gut funktioniert:

Deklarieren Sie zuerst einen Vergleicher, 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;
  };
}

Nun, wenn Sie die Richtung der Sortierung umkehren wollen, müssen wir nur noch:

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 sich Backbone.Collection.sort anders verhält, wenn die Sortierfunktion zwei Argumente hat. In diesem Fall verhält es sich genauso wie der in Array.sort übergebene Array.sort . Diese Lösung funktioniert, indem die Funktion sortBy für ein einzelnes Argument in einen Komparator mit zwei Argumenten angepasst und das Ergebnis umgekehrt wird.

Question

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 und nicht aufsteigend sortieren?




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

});

So können Sie es wie folgt verwenden:

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.




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

collection.models = collection.models.reverse()

Sie können es mit etwas Ähnlichem kombinieren, wenn Sie sich für den Table Case (coffeescript) interessieren:

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

  collection.sort()

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



Ich hatte eine etwas andere Anforderung, indem ich meine Modelle in einer Tabelle anzeigte, und ich wollte sie nach jeder Spalte (Modelleigenschaft) und entweder aufsteigend oder absteigend sortieren können.

Es hat ziemlich viel Mühe gekostet, alle Fälle zum Laufen zu bringen (wo Werte Strings, leere Strings, Dates, Zahlen sein können). Aber ich denke, das ist ziemlich knapp.

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

benutzen:

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



Folgendes hat mir gut getan:

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



Meine Lösung bestand darin, die Ergebnisse nach der Sortierung umzukehren.

Um Doppel-Rendering zu vermeiden, sortiere zuerst mit silent, dann trigger 'reset'.

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



Kürzlich lief dieses Problem und nur beschlossen, eine Rsort-Methode 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 wird jemand das nützlich finden




Links