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

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)

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.


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.


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


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.