So sortieren Sie Zeichenfolgen in JavaScript

Lesezeit: 12 Minuten

So sortieren Sie Zeichenfolgen in JavaScript
Flughafenyh

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

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

aber das gefunden - scheint nicht mit Zeichenfolgen in JavaScript zu funktionieren. Wie kann ich eine Liste von Objekten basierend auf einem Attribut vom Typ Zeichenfolge sortieren?

  • sehen JavaScript case insensitive string comparison auf stackoverflow.com/questions/2140627/…

    – Adrien Be

    26. September 2014 um 10:37 Uhr


  • Für eine schnelle “internationalisierte” Lösung (nur teilweise, denke ich, da dies möglicherweise nicht alle Akzente der Welt abdeckt), möchten Sie vielleicht Akzente einfach ignorieren, dh sie entfernen. Dann machen Sie nur Ihren String-Vergleich, siehe Javascript : remove accents/diacritics in strings auf stackoverflow.com/questions/990904/…

    – Adrien Be

    26. September 2014 um 11:00 Uhr


  • Lustigerweise hat Jeff Atwood selbst 2007 einen Blogbeitrag über dieses häufige Problem geschrieben, siehe blog.codinghorror.com/sorting-for-humans-natural-sort-order

    – Adrien Be

    26. September 2014 um 12:02 Uhr

  • Dies ist eine sehr alte Frage. Wenn Sie also wie ich auf diese Frage aus der Zukunft stoßen, sollten Sie diese Frage zur Leistung wirklich lesen, bevor Sie die hier gefundenen Vorschläge umsetzen.

    – Kodierer

    12. Januar um 15:28 Uhr

So sortieren Sie Zeichenfolgen in JavaScript
Shog9

Verwenden String.prototype.localeCompare a nach deinem beispiel:

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

Wir erzwingen, dass a.attr ein String ist, um Ausnahmen zu vermeiden. localeCompare wurde unterstützt seit Internet Explorer 6 und Firefox 1. Möglicherweise sehen Sie auch den folgenden Code, der kein Gebietsschema berücksichtigt:

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

  • Bevor jemand den gleichen voreiligen Fehler macht wie ich, es ist lokaleVergleichen, nicht localCompare.

    – ent

    9. September 2012 um 9:38 Uhr


  • Die erste Lösung geht davon aus, dass „A“ nach „z“, aber vor „Z“ kommt, da sie einen Vergleich mit dem ASCII-Zeichenwert durchführt. localeCompare() stößt nicht auf dieses Problem, versteht aber keine Zahlen, also werden Sie es bekommen [ “1”, “10”, “2” ] wie bei Sortiervergleichen in den meisten Sprachen. Wenn Sie eine Sortierung für Ihr UI-Frontend wünschen, sehen Sie sich den alphanum/natural sort-Algorithmus an stackoverflow.com/questions/4340227/… oder stackoverflow.com/questions/4321829/…

    – Dead.Rabit

    20. Juni 2013 um 13:22 Uhr


  • Beachten Sie, dass localeCompare() wird nur in modernen Browsern unterstützt: IE11+ zum Zeitpunkt des Schreibens, siehe developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – Adrien Be

    26. September 2014 um 10:39 Uhr

  • Nein, ich meine die erste Zeile der Tabelle, @Adrien – IE unterstützt localeCompare() zurück viele Versionen, aber nicht unterstützt Angabe des Gebietsschemas bis Version 11. Beachten Sie auch die Fragen, auf die Dead.Rabit verlinkt ist.

    – Shog9

    26. September 2014 um 17:54 Uhr

  • @Shog9 mein Fehler, es scheint, als würde es seit IE6 unterstützt! siehe (scroll-down/search to localeCompare() method) on msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx . Beachten Sie jedoch Folgendes: In den alten Implementierungen, in denen wir die Locales- und Optionsargumente nicht verwenden (die vor IE11 verwendeten) Das verwendete Gebietsschema und die verwendete Sortierreihenfolge sind vollständig von der Implementierung abhängig, mit anderen Worten: Firefox, Safari, Chrome & IE sortieren Zeichenfolgen NICHT in der gleichen Reihenfolge. sehen code.google.com/p/v8/issues/detail?id=459

    – Adrien Be

    29. September 2014 um 7:56 Uhr


1646307920 467 So sortieren Sie Zeichenfolgen in JavaScript
Adrian Be

Eine aktualisierte Antwort (Oktober 2014)

Ich war wirklich verärgert über diese natürliche Sortierreihenfolge von Strings, also habe ich mir einige Zeit genommen, um dieses Problem zu untersuchen. Ich hoffe das hilft.

Um es kurz zu machen

localeCompare() Zeichenunterstützung ist knallhart, benutze sie einfach. Wie von betont Shog9die Antwort auf Ihre Frage lautet:

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

Fehler, die in allen benutzerdefinierten Javascript-Implementierungen der “natürlichen Zeichenfolgensortierreihenfolge” gefunden wurden

Es gibt eine ganze Reihe von benutzerdefinierten Implementierungen, die versuchen, einen String-Vergleich durchzuführen, der genauer als “natürliche String-Sortierreihenfolge” bezeichnet wird.

Beim “Spielen” mit diesen Implementierungen ist mir immer eine seltsame Wahl der “natürlichen Sortierreihenfolge” aufgefallen, oder besser gesagt Fehler (oder Auslassungen im besten Fall).

Normalerweise werden Sonderzeichen (Leerzeichen, Bindestrich, kaufmännisches Und, Klammern usw.) nicht korrekt verarbeitet.

Sie werden dann feststellen, dass sie an verschiedenen Stellen durcheinander erscheinen, typischerweise könnte das sein:

  • einige stehen zwischen dem Großbuchstaben „Z“ und dem Kleinbuchstaben „a“.
  • einige werden zwischen der ‘9’ und dem großen ‘A’ stehen
  • einige werden nach Kleinbuchstaben ‘z’ sein

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

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

Recherche zu den benutzerdefinierten Implementierungen:

Die nativen Implementierungen der Browser für die “natürliche Zeichenfolgensortierung” via localeCompare()

localeCompare() Die älteste Implementierung (ohne die Locales- und Optionsargumente) 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()). Das eingebaute localeCompare() -Methode ist beim Sortieren viel besser, sogar bei internationalen und Sonderzeichen. Das einzige Problem mit der localeCompare() Methode ist das “Das verwendete Gebietsschema und die verwendete Sortierreihenfolge sind vollständig von der Implementierung abhängig”. Mit anderen Worten, wenn Sie localeCompare wie stringOne.localeCompare(stringTwo) verwenden: Firefox, Safari, Chrome und IE haben eine andere Sortierreihenfolge für Strings.

Recherche zu den Browser-nativen Implementierungen:

Schwierigkeit der “string natural sorting order”

Die Implementierung eines soliden Algorithmus (d. h. konsistent, aber auch für eine breite Palette von Zeichen) ist eine sehr schwierige Aufgabe. UTF8 enthält mehr als 2000 Zeichen & umfasst mehr als 120 Schriften (Sprachen). Schließlich gibt es einige Spezifikationen für diese Aufgaben, sie werden “Unicode Collation Algorithm” genannt und sind unter zu finden http://www.unicode.org/reports/tr10/ . Weitere Informationen dazu finden Sie in dieser Frage, die ich gepostet habe https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

Schlußfolgerung

In Anbetracht des aktuellen Unterstützungsniveaus der benutzerdefinierten Javascript-Implementierungen, auf die ich gestoßen bin, werden wir wahrscheinlich nie etwas sehen, das auch nur annähernd all diese Zeichen und Skripte (Sprachen) unterstützt. Daher würde ich lieber die native Methode localeCompare() des Browsers verwenden. Ja, es hat den Nachteil, dass es in verschiedenen Browsern nicht konsistent ist, aber grundlegende Tests zeigen, dass es eine viel größere Bandbreite an Zeichen abdeckt und solide und aussagekräftige Sortierreihenfolgen ermöglicht.

Also wie von hervorgehoben Shog9die Antwort auf Ihre Frage lautet:

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

Weiterlesen:

Danke an die nette Antwort von Shog9, die mich, glaube ich, in die “richtige” Richtung gebracht hat

1646307920 722 So sortieren Sie Zeichenfolgen in JavaScript
mpyw

Antwort (in modernem ECMAScript)

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

Oder

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

Beschreibung

Das Umwandeln eines booleschen Werts in eine Zahl ergibt Folgendes:

  • 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

(Alternative)

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

  • Wie ich die frühere Antwort kommentierte, die diesen Trick verwendete, können Nur-Code-Antworten nützlicher gemacht werden, indem erklärt wird, wie sie funktionieren.

    – Dan Dascalescu

    30. Oktober 2018 um 17:31 Uhr

  • Beschreibung hinzugefügt

    – mpyw

    4. November 2018 um 5:33 Uhr

  • Können Sie kommentieren, ob dies besser oder schlechter als localeCompare ist?

    – Ran Lottem

    13. Januar 2019 um 11:35 Uhr

  • @RanLottem localeCompare und Standardvergleich ergeben unterschiedliche Ergebnisse. Welche erwarten Sie? ["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b)) sortiert in alphabetischer Reihenfolge ohne Berücksichtigung der Groß-/Kleinschreibung ["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b)) tut in Codepoint-Reihenfolge

    – mpyw

    13. Januar 2019 um 12:11 Uhr


  • Das ist besser als localeCompare, da localeCompare 0 für Zeichenfolgen zurückgibt, die nicht gleich sind. Konkretes Beispiel: Es gibt (mindestens) zwei verschiedene “Ö”-Symbole, die gleich aussehen, und localeCompare sagt, dass sie gleich sind, aber sie scheitern === (auch wenn sie in Großbuchstaben geschrieben sind). Ihr hübscher UI-Code kann also etwas mit Sortieren und Gruppieren tun, und etwas, das “Ö” mit “Ö” identisch ist, aber Ihre Backend-Logik, die eine Karte verwendet, entscheidet, dass diese beiden Ös unterschiedlich sind, sodass die Dinge schlecht ausgehen.

    – Kevin Frei

    16. Januar 2021 um 23:35 Uhr

Da Zeichenfolgen direkt in Javascript verglichen werden können, wird dies die Aufgabe erledigen

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

Die Subtraktion in einer Sortierfunktion wird nur verwendet, wenn eine nicht alphabetische (numerische) Sortierung gewünscht wird, und funktioniert natürlich nicht mit Zeichenfolgen

So sortieren Sie Zeichenfolgen in JavaScript
Flughafenyh

Sie sollten hier > oder < und == verwenden. Die Lösung wäre also:

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

  • Nebenbei bemerkt, dies wird nicht mit Vergleichen von Zeichenfolgen und Zahlen umgehen. Zum Beispiel: ‘Z’ < 9 (falsch), 'Z' > 9 (auch falsch??), ‘Z’ == 9 (auch falsch!!). Dummes NaN in JavaScript …

    – Kat

    18. Juli 2014 um 17:20 Uhr

1646307921 496 So sortieren Sie Zeichenfolgen in JavaScript
Geckos

Verschachtelte ternäre Pfeilfunktion

(a,b) => (a < b ? -1 : a > b ? 1 : 0)

  • Nebenbei bemerkt, dies wird nicht mit Vergleichen von Zeichenfolgen und Zahlen umgehen. Zum Beispiel: ‘Z’ < 9 (falsch), 'Z' > 9 (auch falsch??), ‘Z’ == 9 (auch falsch!!). Dummes NaN in JavaScript …

    – Kat

    18. Juli 2014 um 17:20 Uhr

1646307921 457 So sortieren Sie Zeichenfolgen in JavaScript
Manav

Ich hatte mich lange darüber Gedanken gemacht, also habe ich das endlich recherchiert und Ihnen diesen langatmigen Grund dafür gegeben, warum die Dinge so sind, wie sie sind.

Von dem spez:

Section 11.9.4   The Strict Equals Operator ( === )

The production EqualityExpression : EqualityExpression === RelationalExpression
is evaluated as follows: 
- Let lref be the result of evaluating EqualityExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating RelationalExpression.
- Let rval be GetValue(rref).
- Return the result of performing the strict equality comparison 
  rval === lval. (See 11.9.6)

Also gehen wir jetzt zu 11.9.6

11.9.6   The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false. 
Such a comparison is performed as follows: 
- If Type(x) is different from Type(y), return false.
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is Number, then
...
- If Type(x) is String, then return true if x and y are exactly the 
  same sequence of characters (same length and same characters in 
  corresponding positions); otherwise, return false.

Das ist es. Der auf Strings angewendete Triple-Equals-Operator gibt „true“ zurück, wenn die Argumente genau die gleichen Strings sind (gleiche Länge und gleiche Zeichen an entsprechenden Positionen).

Damit === funktioniert in den Fällen, in denen wir versuchen, Zeichenfolgen zu vergleichen, die möglicherweise aus verschiedenen Quellen stammen, von denen wir aber wissen, dass sie letztendlich dieselben Werte haben werden – ein Szenario, das häufig genug für Inline-Zeichenfolgen in unserem Code ist. Wenn wir zum Beispiel eine Variable mit dem Namen haben connection_stateund wir möchten wissen, welcher der folgenden Zustände ist ['connecting', 'connected', 'disconnecting', 'disconnected'] ist es gerade drin, können wir das direkt verwenden ===.

Aber es gibt noch mehr. Direkt über 11.9.4 gibt es einen kurzen Hinweis:

NOTE 4     
  Comparison of Strings uses a simple equality test on sequences of code 
  unit values. There is no attempt to use the more complex, semantically oriented
  definitions of character or string equality and collating order defined in the 
  Unicode specification. Therefore Strings values that are canonically equal
  according to the Unicode standard could test as unequal. In effect this 
  algorithm assumes that both Strings are already in normalized form.

Hmm. Was jetzt? Extern erhaltene Strings können und werden höchstwahrscheinlich seltsam unicodey und unsere sanft sein === wird ihnen nicht gerecht. Herein kommt localeCompare zur Rettung:

15.5.4.9   String.prototype.localeCompare (that)
    ...
    The actual return values are implementation-defined to permit implementers 
    to encode additional information in the value, but the function is required 
    to define a total ordering on all Strings and to return 0 when comparing
    Strings that are considered canonically equivalent by the Unicode standard. 

Wir können jetzt nach Hause gehen.

tl;dr;

Verwenden Sie zum Vergleichen von Zeichenfolgen in Javascript localeCompare; wenn Sie wissen, dass die Zeichenketten keine Nicht-ASCII-Komponenten enthalten, weil es sich beispielsweise um interne Programmkonstanten handelt, dann === funktioniert auch.

923040cookie-checkSo sortieren Sie Zeichenfolgen in JavaScript

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy