Wie kann ich mit underscore.js eine Auf- und Abwärtssortierung durchführen?

166

Ich verwende derzeit Unterstriche zum Sortieren meiner JSON-Sortierung. Jetzt habe ich gebeten , eine zu tun ascendingund das descendingSortieren mit Underscore.js. Ich sehe nichts in der Dokumentation. Wie kann ich das erreichen?

Rahul
quelle
1
Bitte fügen Sie ein Beispiel hinzu, was und wie Sie sortieren.
Jon
Was sortierst du? Zahlen? Saiten? Termine? Etwas anderes?
Mu ist zu kurz
@muistooshort Ich sortiere eine Reihe von Objekten. Die sortBy-Methode entspricht also perfekt meinen Kriterien für aufsteigende Sortierung, aber nicht umgekehrt.
Rahul
Wenn Sie nach einer Zahl sortieren, sortBykann Ihre Funktion sein, return -naber das funktioniert nicht für Zeichenfolgen. daher die Frage, welche Art von Dingen Sie sortieren.
Mu ist zu kurz
2
Mit Lodash können Sie eine Kurzform wie _.sortBy([1,4,3,2]).reverse()oder verwenden, _.chain([1,4,3,2]).sortBy().reverse().value()wenn Sie den reverse()Prototyp von Array nicht verwenden möchten .
GFoley83

Antworten:

363

Sie können verwenden .sortBy, es wird immer eine aufsteigende Liste zurückgegeben:

_.sortBy([2, 3, 1], function(num) {
    return num;
}); // [1, 2, 3]

Sie können jedoch die .reverse- Methode verwenden, um sie absteigend zu erhalten :

var array = _.sortBy([2, 3, 1], function(num) {
    return num;
});

console.log(array); // [1, 2, 3]
console.log(array.reverse()); // [3, 2, 1]

Oder fügen Sie beim Umgang mit Zahlen der Rückgabe ein negatives Vorzeichen hinzu, um die Liste abzuleiten:

_.sortBy([-3, -2, 2, 3, 1, 0, -1], function(num) {
    return -num;
}); // [3, 2, 1, 0, -1, -2, -3]

Unter der Haube .sortByverwendet die eingebaute .sort([handler]):

// Default is ascending:
[2, 3, 1].sort(); // [1, 2, 3]

// But can be descending if you provide a sort handler:
[2, 3, 1].sort(function(a, b) {
    // a = current item in array
    // b = next item in array
    return b - a;
});
andlrc
quelle
9
Die letzte Lösung, dh das Hinzufügen eines negativen Vorzeichens zur zurückgegebenen Nummer, ist perfekt.
Vinesh
Warum denkst du, es ist Blasensorte? Unter der Haube sind integrierte .sortBy()Aufrufe enthalten Array.sort(), deren Algorithmus den Browsern überlassen bleibt, aber es ist ziemlich unwahrscheinlich, dass die Blasensortierung ihre Wahl ist.
Rene Saarsoo
Erhöht dies nicht die zeitliche Komplexität? Dadurch wird die Liste zweimal sortiert.
user1477388
@ user1477388 Ich bin nicht sicher, was du mit zweimal sortiert meinst?
andlrc
@andlrc Wenn Sie also aufrufen _.sortBy(arr, function), gehe ich davon aus , dass es jedes Element durchläuft und eine Logik ausführt, um das sortierte Array zurückzugeben. Wenn Sie dann aufrufen Array.prototype.reverse(), wird wahrscheinlich jedes Element erneut durchlaufen und eine Logik ausgeführt, um das umgekehrte Array zurückzugeben. Daher schleifen Sie das Array zweimal.
user1477388
57

Eine absteigende Reihenfolge mit Unterstrich kann durch Multiplizieren des Rückgabewerts mit -1 erfolgen.

//Ascending Order:
_.sortBy([2, 3, 1], function(num){
    return num;
}); // [1, 2, 3]


//Descending Order:
_.sortBy([2, 3, 1], function(num){
    return num * -1;
}); // [3, 2, 1]

Wenn Sie nach Zeichenfolgen und nicht nach Zahlen sortieren, können Sie die Methode charCodeAt () verwenden, um den Unicode-Wert abzurufen.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});
jEremyB
quelle
3
Ich versuche alphabetisch zu sortieren - das Multiplizieren mit -1 ist keine gültige Operation. :)
Rythos42
Es ist ein lohnender Anwendungsfall, aber nicht in der Frage angegeben. Das Multiplizieren einer Zeichenfolge mit -1 ist jedoch eine gültige Operation. Es gibt NaN zurück, was ein gültiges Ergebnis ist.
jEremyB
1
Denken Sie daran, das Array auch wieder zuzuweisen! SOME_ARR = _.sortBy (SOME_ARR, Funktion (num) {SOME_FUNC ...});
aqm
4
charCodeAt wird „Rückkehr der Unicode des Zeichens an dem angegebenen Index in einer Zeichenfolge“ so kann er durch Zeichen in einer Zeichenfolge zu sortieren verwendet werden, aber wie es gezeigt tut nicht „sortiert nach string“ es sortiert durch ein Zeichen in der Zeichenfolge
Anthony
2
Dies sortiert nur nach dem ersten Zeichen und unterscheidet zwischen Groß- und Kleinschreibung.
Aidan
50

Die umgekehrte Methode des Array-Prototyps ändert das Array und gibt einen Verweis darauf zurück. Dies bedeutet, dass Sie Folgendes tun können:

var sortedAsc = _.sortBy(collection, 'propertyName');
var sortedDesc = _.sortBy(collection, 'propertyName').reverse();

Die Unterstreichungsdokumentation lautet außerdem:

Darüber hinaus werden die Methoden des Array-Prototyps über das verkettete Unterstrichobjekt übertragen, sodass Sie ein reverseoder ein pushin Ihre Kette einfügen und das Array weiter ändern können.

was bedeutet, dass Sie auch .reverse()während der Verkettung verwenden können:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();
Emil Lundberg
quelle
Dies ist die einfachste Methode für die umgekehrte / absteigende Sortierung, wenn es um die einfachsten Anwendungsfälle geht.
Dan Atkinson
2
Um eine alphabetische Sortierung _.sortBy(collection, item => item. propertyName.toLowerCase());
ohne Berücksichtigung der
Dies funktioniert nicht, wenn das Array negative Zahlen enthält.
Shruti Kapoor
@ ShrutiKapoor Ja, das tut es. Warum sollte es nicht?
Emil Lundberg
5
In Bezug auf die Leistung ist es vorzuziehen, zuerst den Filter anzuwenden und dann (die verbleibenden) Werte zu sortieren.
Saran
12

Ähnlich wie bei der Underscore-Bibliothek gibt es eine andere Bibliothek namens 'lodash' mit einer Methode "orderBy", die den Parameter verwendet, um zu bestimmen, in welcher Reihenfolge sie sortiert werden soll. Sie können es wie verwenden

_.orderBy('collection', 'propertyName', 'desc')

Aus irgendeinem Grund ist es nicht in den Website-Dokumenten dokumentiert.

Minkesh Jain
quelle
Ich denke, Sie haben den Unterstrich mit lodash verwechselt . Nur letzteres hat die erwähnte orderBy-Funktion .
Thomas Marti
Ja, mein schlechtes. Aktualisiert die Antwort. Danke für die Korrektur :)
Minkesh Jain
orderBy, super nützlich! Viel besser als die Verwendung von umgekehrt, da die von mir gesuchte stabile Sortiereigenschaft erhalten bleibt.
Flimm
Aus irgendeinem Grund nicht für mich arbeiten upadte: seine lodash (
aleXela
0

Unterstreichen Sie Mixins

Wenn Sie die Antwort von @ emil_lundberg erweitern, können Sie auch ein "Mixin" schreiben, wenn Sie Underscore verwenden, um eine benutzerdefinierte Funktion zum Sortieren zu erstellen, wenn es sich um eine Art Sortieren handelt, die Sie möglicherweise irgendwo in einer Anwendung wiederholen.

Wenn Sie beispielsweise einen Controller haben oder Sortierergebnisse mit der Sortierreihenfolge "ASC" oder "DESC" anzeigen und zwischen diesen Sortierungen wechseln möchten, können Sie Folgendes tun:

Mixin.js

_.mixin({
    sortByOrder: function(stooges, prop, order) {
      if (String(order) === "desc") {
          return _.sortBy(stooges, prop).reverse();
      } else if (String(order) === "asc") {
          return _.sortBy(stooges, prop);
      } else {
          return stooges;
      }
    }
})

Anwendungsbeispiel

var sort_order = "asc";
var stooges = [
  {name: 'moe', age: 40}, 
  {name: 'larry', age: 50}, 
  {name: 'curly', age: 60},
  {name: 'July', age: 35},
  {name: 'mel', age: 38}
 ];

_.mixin({
    sortByOrder: function(stooges, prop, order) {
    if (String(order) === "desc") {
        return _.sortBy(stooges, prop).reverse();
    } else if (String(order) === "asc") {
        return _.sortBy(stooges, prop);
    } else {
        return stooges;
    }
  }
})


// find elements
var banner = $("#banner-message");
var sort_name_btn = $("button.sort-name");
var sort_age_btn = $("button.sort-age");

function showSortedResults(results, sort_order, prop) {
    banner.empty();
    banner.append("<p>Sorting: " + prop + ', ' + sort_order + "</p><hr>")
  _.each(results, function(r) {
    banner.append('<li>' + r.name + ' is '+ r.age + ' years old.</li>');
  }) 
}

// handle click and add class
sort_name_btn.on("click", function() {
  sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'name', sort_order);
  showSortedResults(sortedResults, sort_order, 'name');
})

sort_age_btn.on('click', function() {
    sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'age', sort_order);
  showSortedResults(sortedResults, sort_order, 'age');
})

Hier ist eine JSFiddle, die dies demonstriert: JSFiddle für SortBy Mixin

RoboBear
quelle