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/…
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.
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/…
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
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:
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:
Danke an die nette Antwort von Shog9, die mich, glaube ich, in die “richtige” Richtung gebracht hat
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
Die Subtraktion in einer Sortierfunktion wird nur verwendet, wenn eine nicht alphabetische (numerische) Sortierung gewünscht wird, und funktioniert natürlich nicht mit Zeichenfolgen
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
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
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.
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.
9230400cookie-checkSo sortieren Sie Zeichenfolgen in JavaScriptyes
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