Gibt es ein JavaScript strcmp ()?


Antworten:


134

Wie wäre es mit

str1.localeCompare(str2)

localeCompare () sah gut aus, aber es sah so aus, als wäre es nur MS oder bestenfalls nicht im Standard.

10
Welchen Standard suchen Sie? Es scheint im ECMA-262-Standardabschnitt 15.5.4.9 sowie in der Mozilla-Javascript-Referenz ( developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… )
newacct

newacct ist absolut korrekt. Dies scheint der ECMAScript-Standard zu sein. Wahrscheinlich die beste Lösung in diesem Fall.
Coderjoe

3
localeCompare()verhält sich manchmal in jedem Browser anders.
Varda Elentári

1
@ VardaElentári: Nur für Zeichen, die im angegebenen Gebietsschema keine lexikalische Reihenfolge haben. Für Zeichen, die dies tun, und für Browser, die nicht einschränken, welche Teile von Unicode sie verwenden, sind die Ergebnisse konsistent und werden von ECMA-402 und Unicode definiert .
TJ Crowder

38

Javascript hat es nicht, wie Sie betonen.

Eine schnelle Suche ergab:

function strcmp ( str1, str2 ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Waldo Malqui Silva
    // +      input by: Steve Hilder
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: gorthaur
    // *     example 1: strcmp( 'waldo', 'owald' );
    // *     returns 1: 1
    // *     example 2: strcmp( 'owald', 'waldo' );
    // *     returns 2: -1

    return ( ( str1 == str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );
}

von http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_strcmp/

Natürlich können Sie bei Bedarf auch localeCompare hinzufügen:

if (typeof(String.prototype.localeCompare) === 'undefined') {
    String.prototype.localeCompare = function(str, locale, options) {
        return ((this == str) ? 0 : ((this > str) ? 1 : -1));
    };
}

Und str1.localeCompare(str2)überall verwenden, ohne sich Sorgen machen zu müssen, ob der lokale Browser mitgeliefert wurde. Das einzige Problem ist, dass Sie Unterstützung hinzufügen müssten localesundoptions wenn Sie sich dafür interessieren.


Ich denke, dies ist eine gute Möglichkeit, damit umzugehen (Feature-Erkennung und Polyfill-FTW), aber wenn die Leistung der Mikrogeschwindigkeit so wichtig ist, wie für die Notwendigkeit dieser Methode, dann bin ich ein wenig verwirrt, dass sie ==verwendet wird und nicht, ===da letztere vermeiden Typumwandlung und damit ist diese Mikrosekunde schneller.
Tokimon

Ein Hinweis auf der Polyfüllung - localeCompare unterscheidet nicht zwischen Groß- und Kleinschreibung. Um die Polyfüllung auch nicht zwischen Groß- und Kleinschreibung zu unterscheiden, können Sie Folgendes tun: var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Kip

22

localeCompare()ist langsam . Wenn Sie sich also nicht für die "richtige" Reihenfolge von Zeichenfolgen interessieren, die nicht aus Englisch stammen, versuchen Sie es mit Ihrer ursprünglichen Methode oder der saubereren:

str1 < str2 ? -1 : +(str1 > str2)

Dies ist eine Größenordnung schneller als localeCompare()auf meiner Maschine.

Das +stellt sicher, dass die Antwort immer numerisch und nicht boolesch ist.


Zwei Fehler: gibt nicht 0 für str1 == str2 zurück, gibt nicht 1 für str1> str2 zurück
stackunderflow

2
@stackunderflow Ich verwende es erfolgreich in einer Sortierfunktion. Was ist der Fehler, den Sie haben?
1.

1
Dies gibt -1, false oder true anstelle von -1, 0 oder 1 zurück. Damit immer Zahlen zurückgegeben werden, passen Sie es wie folgt an: str1 <str2? -1: + (str1> str2)
jfren484

2
Eine weitere Sache (ich verwende dies in Code, den ich gerade schreibe, also habe ich es perfektioniert): Beachten Sie nur, dass dies ein Vergleich ist, bei dem zwischen Groß- und Kleinschreibung unterschieden wird ('Foo' wird vor 'bar' stehen, aber ' Bar 'kommt nach' foo '). Das entspricht der Frage von OP zu strcmp, aber viele Leute kommen hierher, um einen fallunabhängigen Vergleich zu suchen.
jfren484

5
Hier ist ein noch sauberer aussehender Ausdruck:(str1 > str2) - (str1 < str2)
Jonathan Gilbert

2
var strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;

Verwendung: strcmp(string1, string2)

Ergebnis: 1bedeutet, dass string1 größer ist, 0bedeutet gleich, -1bedeutet , dass string2 größer ist.

Dies hat eine höhere Leistung als String.prototype.localeCompare

Auch numeric:truemacht es tun logische Nummer Vergleich



-1

Wie wäre es mit:

String.prototype.strcmp = function(s) {
    if (this < s) return -1;
    if (this > s) return 1;
    return 0;
}

Dann, um s1 mit 2 zu vergleichen:

s1.strcmp(s2)

1
Es wäre hilfreich, wenn Sie sagen würden, warum sie nicht das tun sollten, was sie getan haben. Ich könnte verstehen, ob sie die Funktionsweise einer vorhandenen Funktionsmethode ändern, aber in diesem Fall fügen sie eine neue hinzu.
Entspannen in Zypern

2
Die bedingungslose Erweiterung von Prototypen ist im Allgemeinen ein großes Nein-Nein.
Christopher
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.