Czy istnieje JavaScript strcmp ()?

127

Czy ktoś może to dla mnie zweryfikować? JavaScript nie ma wersji strcmp (), więc musisz napisać coś takiego:

 ( str1 < str2 ) ? 
            -1 : 
             ( str1 > str2 ? 1 : 0 );
Karel Bílek
źródło
Nie jesteś sam - inni już to robili . Projekt PHP.JS faktycznie zrobił to również dla wielu innych popularnych funkcji. To przydatne źródło informacji.
Reed Copsey

Odpowiedzi:

136

Co powiesz na

str1.localeCompare(str2)
newacct
źródło
localeCompare () wyglądało dobrze, ale wyglądało na to, że było to tylko MS lub w najlepszym razie nie w standardzie.
10
na jaki standard patrzysz? wydaje się, że znajduje się w sekcji 15.5.4.9 standardu ECMA-262, a także w dokumentacji Javascript
Mozilli
newacct jest absolutnie poprawne. Wydaje się, że jest to standard ECMAScript. Chyba najlepsze rozwiązanie w tym przypadku.
coderjoe
3
localeCompare()czasami zachowuje się inaczej w każdej przeglądarce.
Varda Elentári
1
@ VardaElentári: Tylko dla znaków, które nie mają kolejności leksykalnej w podanych ustawieniach regionalnych. W przypadku znaków, które to robią i przeglądarek, które nie ograniczają używanych części Unicode, wyniki są spójne i zdefiniowane przez ECMA-402 i Unicode .
TJ Crowder,
38

Jak zauważyłeś, JavaScript go nie ma.

Pojawiło się szybkie wyszukiwanie:

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

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

Oczywiście w razie potrzeby możesz po prostu dodać localeCompare:

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

Używaj str1.localeCompare(str2)wszędzie, bez martwienia się, czy lokalna przeglądarka została dostarczona z nią. Jedynym problemem jest to, że musiałbyś dodać obsługę localesioptions czy ci na tym zależy.

Esteban Küber
źródło
Myślę, że to fajny sposób radzenia sobie z tym (wykrywanie cech i polyfill FTW), ale jeśli wydajność mikro prędkości jest tak ważna, jak na potrzeby tej metody, to jestem trochę zdziwiony, że ==jest używany, a nie ===skoro ten ostatni omija konwersja typu, a tym samym jest o mikro sekundę szybciej.
Tokimon
uwaga na wypełnieniu - localeCompare nie jest rozróżniana wielkości liter, więc aby polifill również nie rozróżniał wielkości liter, możesz zrobić coś takiego var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Kip
23

localeCompare()jest powolny , więc jeśli nie zależy Ci na „prawidłowej” kolejności ciągów znaków innych niż angielskie, wypróbuj swoją oryginalną metodę lub bardziej przejrzystą:

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

To o rząd wielkości szybciej niż localeCompare()na moim komputerze.

W +gwarantuje, że odpowiedź jest zawsze numerycznej zamiast logiczna.

1 ''
źródło
Dwa błędy: nie zwraca 0 dla str1 == str2, nie zwraca 1 dla str1>
str2
2
@stackunderflow Używam go z powodzeniem w funkcji sortowania. Jaki jest błąd, którego doświadczasz?
1 ''
1
Zwróci to -1, false lub true zamiast -1, 0 lub 1. Aby zawsze zwracało liczby, dostosuj to w ten sposób: słowo1 <słowo2? -1: + (str1>
str2
2
Jeszcze jedno (używam tego w kodzie, który teraz piszę, więc doskonaliłem go): po prostu pamiętaj, że jest to porównanie z uwzględnieniem wielkości liter („Foo” pojawi się przed „bar” ale „ Bar „pojawi się po„ foo ”). Odpowiada to pytaniu OP o strcmp, ale wiele osób może tu przyjść, szukając porównania niezależnego od przypadku.
jfren484
5
Oto jeszcze bardziej przejrzyste wyrażenie:(str1 > str2) - (str1 < str2)
Jonathan Gilbert
2
var strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;

Stosowanie: strcmp(string1, string2)

Wynik: 1oznacza, że ​​ciąg1 jest większy, 0oznacza równy, -1oznacza , że ciąg2 jest większy.

Ma to wyższą wydajność niż String.prototype.localeCompare

Ponadto numeric:trueumożliwia logiczne porównywanie liczb

Anonimowy
źródło
-1

Co powiesz na:

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

Następnie, aby porównać s1 z 2:

s1.strcmp(s2)
Panos Papadopoulos
źródło
1
Pomogłoby, gdybyś powiedział, dlaczego nie powinni robić tego, co zrobili. Zrozumiałbym, gdyby zmieniali sposób działania istniejącej metody funkcji, ale w tym przypadku dodają nową.
Relaks na Cyprze
2
Bezwarunkowe rozszerzanie prototypów w ten sposób jest generalnie wielkim nie-nie.
Christopher