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?

14voto

geckos Punkte 4724

Verschachtelte ternäre Pfeilfunktion

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

9voto

tash Punkte 361

Eine Erklärung, warum der Ansatz in der Frage nicht funktioniert:

let products = [
    { name: "laptop", price: 800 },
    { name: "phone", price:200},
    { name: "tv", price: 1200}
];
products.sort( (a, b) => {
    {let value= a.name - b.name; console.log(value); return value}
});

> 2 NaN

Die Subtraktion zwischen Zeichenketten ergibt NaN.

Die Antwort von @Alejadro aufgreifend, ist der richtige Ansatz

products.sort( (a,b) => a.name > b.name ? 1 : -1 )

9voto

Felix Orinda Punkte 367

In Javascript verwenden wir die .localCompare Methode zum Sortieren von Zeichenketten

Für Typescript

const data = ["jane", "mike", "salome", "ababus", "buisa", "dennis"];

const sort = (arr: string[], mode?: 'desc' | 'asc') => 
  !mode || mode === "asc"
    ? arr.sort((a, b) => a.localeCompare(b))
    : arr.sort((a, b) => b.localeCompare(a));

console.log(sort(data, 'desc'));// [ 'salome', 'mike', 'jane', 'dennis', 'buisa', 'ababus' ]
console.log(sort(data, 'asc')); // [ 'ababus', 'buisa', 'dennis', 'jane', 'mike', 'salome' ]

Für JS

const data = ["jane", "mike", "salome", "ababus", "buisa", "dennis"];

/**
 * @param {string[]} arr
 * @param {"asc"|"desc"} mode
 */
const sort = (arr, mode = "asc") =>
  !mode || mode === "asc"
    ? arr.sort((a, b) => a.localeCompare(b))
    : arr.sort((a, b) => b.localeCompare(a));

console.log(sort(data, 'desc'));// [ 'salome', 'mike', 'jane', 'dennis', 'buisa', 'ababus' ]
console.log(sort(data, 'asc')); // [ 'ababus', 'buisa', 'dennis', 'jane', 'mike', 'salome' ]

8voto

Manav Punkte 9546

Ich habe mich schon lange darüber aufgeregt, also habe ich schließlich recherchiert und gebe Ihnen diese langatmige Begründung, warum die Dinge so sind, wie sie sind.

De la spec :

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 war's. Der dreifache Gleichheitsoperator, der auf Zeichenketten angewandt wird, gibt true zurück, wenn die Argumente genau die gleichen Zeichenketten sind (gleiche Länge und gleiche Zeichen an den entsprechenden Positionen).

Así que === funktioniert in den Fällen, in denen wir versuchen, Zeichenketten zu vergleichen, die aus unterschiedlichen Quellen stammen könnten, von denen wir aber wissen, dass sie letztendlich die gleichen Werte haben werden - ein häufig genug vorkommendes Szenario für Inline-Zeichenketten in unserem Code. Wenn wir zum Beispiel eine Variable namens connection_state und wir möchten wissen, welcher der folgenden Zustände ['connecting', 'connected', 'disconnecting', 'disconnected'] ist, können wir direkt die Funktion === .

Aber es gibt noch mehr. Direkt über 11.9.4 gibt es eine kurze Notiz:

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.

Hm. Was nun? Extern beschaffte Saiten können und werden höchstwahrscheinlich seltsam einfarbig sein, und unsere sanften === wird ihnen nicht gerecht. Rein 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;

Um Zeichenketten in Javascript zu vergleichen, verwenden Sie localeCompare Wenn Sie wissen, dass die Zeichenketten keine Nicht-ASCII-Bestandteile haben, weil es sich z. B. um interne Programmkonstanten handelt, dann === funktioniert auch.

6voto

xmedeko Punkte 6370

Wenn Sie Sprachumgebungen (oder Groß- und Kleinschreibung oder Akzente) kontrollieren wollen, verwenden Sie Intl.collator :

const collator = new Intl.Collator();
list.sort((a, b) => collator.compare(a.attr, b.attr));

Sie können den Kollator wie folgt konstruieren:

new Intl.Collator("en");
new Intl.Collator("en", {sensitivity: "case"});
...

siehe den obigen Link für das Dokument.

Hinweis: Im Gegensatz zu einigen anderen Lösungen, behandelt es null, undefined den JS-Weg, d. h. er verschiebt sie an das Ende.

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