Existe-t-il un strcmp JavaScript ()?

127

Quelqu'un peut-il vérifier cela pour moi? JavaScript n'a pas de version de strcmp (), vous devez donc écrire quelque chose comme:

 ( str1 < str2 ) ? 
            -1 : 
             ( str1 > str2 ? 1 : 0 );
Karel Bílek
la source
Vous n'êtes pas seul - d' autres personnes l'ont déjà fait . Le projet PHP.JS l' a également fait pour de nombreuses autres fonctions courantes. C'est une ressource pratique.
Reed Copsey

Réponses:

134

Qu'en est-il de

str1.localeCompare(str2)
newacct
la source
localeCompare () avait l'air bien, mais il semblait que c'était uniquement MS, ou au mieux pas dans la norme.
10
quelle norme regardez-vous? il semble être dans la section standard ECMA-262 15.5.4.9, ainsi que dans la référence javascript mozilla ( developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… )
newacct
newacct est absolument correct. Cela semble être la norme ECMAScript. Probablement la meilleure solution dans ce cas.
coderjoe
3
localeCompare()se comporte parfois différemment sur chaque navigateur.
Varda Elentári
1
@ VardaElentári: Uniquement pour les caractères sans ordre lexical dans la locale donnée. Pour les caractères qui le font et les navigateurs qui ne restreignent pas les parties d'Unicode qu'ils utilisent, les résultats sont cohérents et définis par ECMA-402 et Unicode .
TJ Crowder
38

Javascript ne l'a pas, comme vous le faites remarquer.

Une recherche rapide est venue avec:

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

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

Bien sûr, vous pouvez simplement ajouter localeCompare si nécessaire:

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

Et utilisez-le str1.localeCompare(str2)partout, sans vous soucier de savoir si le navigateur local est livré avec. Le seul problème est que vous devrez ajouter un support pour localesetoptions si cela vous intéresse.

Esteban Küber
la source
Je pense que c'est une bonne façon de le gérer (détection des fonctionnalités et polyfill FTW), mais si les performances de la micro vitesse sont si importantes, quant à la nécessité de cette méthode, alors je suis un peu perplexe sur ce qui ==est utilisé et non ===puisque ce dernier évite conversion de type et est donc cette micro seconde plus rapide.
Tokimon
une note sur le polyfill - localeCompare n'est pas sensible à la casse, donc pour rendre le polyfill également non sensible à la casse, vous pouvez faire quelque chose comme- var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Kip le
22

localeCompare()est lent , donc si vous ne vous souciez pas du "bon" ordre des chaînes de caractères non anglais, essayez votre méthode originale ou la plus propre:

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

C'est un ordre de grandeur plus rapide que localeCompare() sur ma machine.

Le +garantit que la réponse est toujours numérique plutôt que booléenne.

1''
la source
Deux bogues: ne retourne pas 0 pour str1 == str2, ne renvoie pas 1 pour str1> str2
stackunderflow
2
@stackunderflow Je l'utilise avec succès dans une fonction de tri. Quel est le bug que vous rencontrez?
1 ''
1
Cela renverra -1, faux ou vrai au lieu de -1, 0 ou 1. Pour qu'il renvoie toujours des nombres, ajustez-le comme ceci: str1 <str2? -1: + (str1> str2)
jfren484
2
Une dernière chose (j'utilise ceci dans le code que j'écris en ce moment, donc je l'ai perfectionné): sachez simplement qu'il s'agit d'une comparaison sensible à la casse ('Foo' viendra avant 'bar' mais ' Bar 'viendra après' foo '). Cela correspond à la question d'OP sur strcmp, mais de nombreuses personnes peuvent venir ici à la recherche d'une comparaison indépendante du cas.
jfren484
5
Voici une expression encore plus propre:(str1 > str2) - (str1 < str2)
Jonathan Gilbert
2
var strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;

Usage: strcmp(string1, string2)

Résultat: 1signifie que string1 est plus grand, 0signifie égal, -1signifie que string2 est plus grand.

Cela a des performances plus élevées que String.prototype.localeCompare

En outre, numeric:trueil fait une comparaison logique des nombres

Anonyme
la source
-1

Que diriez-vous:

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

Ensuite, pour comparer s1 avec 2:

s1.strcmp(s2)
Panos Papadopoulos
la source
1
Il serait utile que vous disiez pourquoi ils ne devraient pas faire ce qu'ils ont fait. Je pourrais comprendre s'ils modifiaient le fonctionnement d'une méthode de fonction existante, mais dans ce cas, ils en ajoutent une nouvelle.
Détente à Chypre
2
Étendre des prototypes inconditionnellement comme celui-ci est généralement un grand non-non.
Christopher