537 Stimmen

Sortieren von Zeichenketten in JavaScript

Ich habe eine Liste von Objekten, die ich nach einem Feld sortieren möchte attr vom Typ String. Ich habe versucht, mit -

list.sort(function (a, b) {
    return a.attr - b.attr
})

aber festgestellt, dass - scheint mit Strings in JavaScript nicht zu funktionieren. Wie kann ich eine Liste von Objekten anhand eines Attributs vom Typ String sortieren?

922voto

Shog9 Punkte 151504

Utilice String.prototype.localeCompare a nach Ihrem Beispiel:

list.sort(function (a, b) {
    return ('' + a.attr).localeCompare(b.attr);
})

Wir zwingen a.attr, eine Zeichenkette zu sein, um Ausnahmen zu vermeiden. localeCompare wurde unterstützt seit Internet Explorer 6 und Firefox 1. Möglicherweise wird auch der folgende Code verwendet, der kein Gebietsschema beachtet:

if (item1.attr < item2.attr)
  return -1;
if ( item1.attr > item2.attr)
  return 1;
return 0;

224voto

Adrien Be Punkte 18445

Eine aktualisierte Antwort (Oktober 2014)

Ich war wirklich verärgert über diese natürliche Sortierreihenfolge der Zeichenketten und habe mir viel Zeit genommen, um dieses Problem zu untersuchen. Ich hoffe, das hilft.

Lange Rede kurzer Sinn

localeCompare() Charakterunterstützung ist knallhart, benutze sie einfach. Wie bereits erwähnt von Shog9 lautet die Antwort auf Ihre Frage:

return item1.attr.localeCompare(item2.attr);

Fehler in allen benutzerdefinierten Javascript-Implementierungen der "natürlichen String-Sortierreihenfolge" gefunden

Es gibt eine ganze Reihe von benutzerdefinierten Implementierungen, die versuchen, String-Vergleiche durchzuführen, genauer gesagt "natürliche String-Sortierreihenfolge".

Beim "Spielen" mit diesen Implementierungen fielen mir immer wieder seltsame "natürliche Sortierreihenfolgen" auf, oder vielmehr Fehler (oder Auslassungen in den besten Fällen).

In der Regel werden Sonderzeichen (Leerzeichen, Bindestriche, kaufmännische Zeichen, Klammern usw.) nicht korrekt verarbeitet.

Sie erscheinen dann an verschiedenen Stellen durcheinander, was typischerweise der Fall ist:

  • einige werden zwischen dem großen 'Z' und dem kleinen 'a' stehen
  • einige werden zwischen der '9' und dem Großbuchstaben 'A' stehen
  • einige werden nach dem Kleinbuchstaben 'z' stehen

Wenn man erwartet hätte, dass Sonderzeichen alle an einer Stelle "gruppiert" sind, außer vielleicht dem Sonderzeichen Leerzeichen (das immer das erste Zeichen ist). Das heißt, entweder alle vor den Zahlen, oder alle zwischen Zahlen und Buchstaben (Klein- und Großbuchstaben nacheinander "zusammen"), oder alle nach den Buchstaben.

Meine Schlussfolgerung ist, dass sie alle keine konsistente Reihenfolge liefern, wenn ich anfange, kaum ungewöhnliche Zeichen hinzuzufügen (d. h. Zeichen mit diakritischen Zeichen oder Zeichen wie Bindestrich, Ausrufezeichen usw.).

Forschung zu den benutzerdefinierten Implementierungen:

Browser-eigene Implementierungen der "natürlichen Stringsortierung" über localeCompare()

localeCompare() älteste Implementierung (ohne die Argumente locales und options) wird von IE6+ unterstützt, siehe http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (scrollen Sie nach unten zur Methode localeCompare()). Die eingebaute localeCompare() Methode sortiert viel besser, auch bei internationalen und Sonderzeichen. Das einzige Problem bei der Verwendung der localeCompare() Methode ist, dass "das verwendete Gebietsschema und die Sortierreihenfolge sind vollständig von der Implementierung abhängig". Mit anderen Worten, bei Verwendung von localeCompare wie stringOne.localeCompare(stringTwo): Firefox, Safari, Chrome und IE haben eine andere Sortierreihenfolge für Strings.

Forschung zu den browserbasierten Implementierungen:

Schwierigkeit der "natürlichen Sortierreihenfolge"

Die Implementierung eines soliden Algorithmus (d.h. konsistent, aber auch eine breite Palette von Zeichen abdeckend) ist eine sehr schwierige Aufgabe. UTF8 enthält mehr als 2000 Zeichen & umfasst mehr als 120 Skripte (Sprachen) . Schließlich gibt es eine Spezifikation für diese Aufgaben, den sogenannten "Unicode Collation Algorithm", der unter folgender Adresse zu finden ist http://www.unicode.org/reports/tr10/ . Weitere Informationen hierzu finden Sie in dieser von mir gestellten Frage https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

Endgültige Schlussfolgerung

Also in Anbetracht der aktuellen Ebene der Unterstützung durch die Javascript benutzerdefinierte Implementierungen, die ich kam über, werden wir wahrscheinlich nie sehen, etwas immer in der Nähe der Unterstützung all dieser Zeichen und Skripte (Sprachen). Daher würde ich lieber die Browser 'native localeCompare() Methode verwenden. Ja, es hat den Nachteil des Seins nicht konsistent zwischen den Browsern, aber grundlegende Tests zeigt es deckt eine viel breitere Palette von Zeichen, so dass solide und sinnvolle Sortierreihenfolgen.

Wie also von Shog9 lautet die Antwort auf Ihre Frage:

return item1.attr.localeCompare(item2.attr);

Lesen Sie weiter:

Dank der netten Antwort von Shog9, die mich in die "richtige" Richtung gebracht hat, glaube ich

75voto

mpyw Punkte 5321

Antwort (in Modern ECMAScript)

list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))

O

list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))

Beschreibung

Die Umwandlung eines booleschen Wertes in eine Zahl ergibt folgendes Ergebnis:

  • true -> 1
  • false -> 0

Betrachten Sie drei mögliche Muster:

  • x ist größer als y: (x > y) - (y < x) -> 1 - 0 -> 1
  • x ist gleich y: (x > y) - (y < x) -> 0 - 0 -> 0
  • x ist kleiner als y: (x > y) - (y < x) -> 0 - 1 -> -1

(Alternativ)

  • x ist größer als y: +(x > y) || -(x < y) -> 1 || 0 -> 1
  • x ist gleich y: +(x > y) || -(x < y) -> 0 || 0 -> 0
  • x ist kleiner als y: +(x > y) || -(x < y) -> 0 || -1 -> -1

Diese Logiken sind also äquivalent zu typischen Sortierkomparatorfunktionen.

if (x == y) {
    return 0;
}
return x > y ? 1 : -1;

29voto

Da Zeichenketten direkt in Javascript verglichen werden können, wird dies die Arbeit erledigen

list.sort(function (a, b) {
    return a.attr > b.attr ? 1: -1;
})

die Subtraktion in einer Sortierfunktion wird nur verwendet, wenn nicht alphabetisch (numerisch) sortiert werden soll, und funktioniert natürlich nicht mit Zeichenketten

16voto

airportyh Punkte 20678

Sie sollten hier > oder < und == verwenden. Die Lösung würde also lauten:

list.sort(function(item1, item2) {
    var val1 = item1.attr,
        val2 = item2.attr;
    if (val1 == val2) return 0;
    if (val1 > val2) return 1;
    if (val1 < val2) return -1;
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X