Gibt es ein JavaScript strcmp ()?

127

Kann jemand dies für mich überprüfen? JavaScript hat keine Version von strcmp (), daher müssen Sie Folgendes schreiben:

 ( str1 < str2 ) ? 
            -1 : 
             ( str1 > str2 ? 1 : 0 );
Karel Bílek
quelle
Du bist nicht allein - andere Leute haben das schon einmal gemacht . Das PHP.JS-Projekt hat dies tatsächlich auch für viele andere allgemeine Funktionen getan. Es ist eine praktische Ressource.
Reed Copsey

Antworten:

134

Wie wäre es mit

str1.localeCompare(str2)
newacct
quelle
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.

Esteban Küber
quelle
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.

1 ''
quelle
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

Anonym
quelle
-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)
Panos Papadopoulos
quelle
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