456 votes

Quelle est la meilleure façon de comparer des chaînes de caractères en JavaScript ?

J'essaie d'optimiser une fonction qui effectue une recherche binaire de chaînes de caractères en JavaScript.

La recherche binaire exige que vous sachiez si la clé est == le pivot ou < le pivot.

Mais cela nécessite deux comparaisons de chaînes de caractères en JavaScript, contrairement à ce qui se passe en C comme les langues qui ont la strcmp() qui renvoie trois valeurs (-1, 0, +1) pour (inférieur à, égal à, supérieur à).

Existe-t-il une telle fonction native en JavaScript, qui peut renvoyer une valeur ternaire de sorte qu'une seule comparaison soit nécessaire à chaque itération de la recherche binaire ?

12 votes

return str1 < str2 ? -1 : str1 > str2; ?

3 votes

@1" Ce n'est pas optimal ; cela nécessite deux comparaisons de chaînes.

3 votes

C'est toujours un ordre de grandeur ( !) plus rapide que localeCompare() sur ma machine. @Gumbo's custom strcmp() peut être plus rapide, en fonction de l'optimisation de l'implémentation interne des comparaisons d'égalité pour les chaînes de caractères.

614voto

Daniel Vassallo Points 142049

Vous pouvez utiliser le localeCompare() méthode.

string_a.localeCompare(string_b);

/* Expected Returns:

 0:  exact match

-1:  string_a < string_b

 1:  string_a > string_b

 */

Pour en savoir plus :

14 votes

Malheureusement, stringCompare n'est pas fiable. Opera, IE, Firefox, Chrome et Safari renvoient tous 1 pour 'dog'.localeCompare('cat'), ce qui est normal, et -1 lorsque vous inversez l'appelant et l'argument. Mais les majuscules se comportent bizarrement - 'dog'.localeCompare('Dog') Parmi les navigateurs que j'ai testés, seul Safari 4 renvoie 1. Il renvoie -1 dans IE8 et Firefox 3, et Opera 9 et Chrome renvoient tous deux +32.

27 votes

Vous pouvez utiliser toLowerCase ou toLocaleLowerCase pour effectuer des comparaisons sans tenir compte de la casse.

2 votes

Je pense qu'il est important de noter que V8 (Chrome) semble interpréter ECMA-262 différemment d'IE/Firefox sur localeCompare. Par exemple, "a".localeCompare("Z") "a".localeCompare("Z") devrait renvoyer -1 mais renvoie plutôt 7 qui est le charcode de "a" - charcode de "Z". Malheureusement, le langage utilisé dans la spécification n'est pas très précis, spécifiant que localeCompare() renvoie un nombre négatif, un nombre positif ou 0. (Pas spécifiquement -1, 1, 0). J'ai rempli un rapport de bogue dans l'espoir que cela change, mais c'est un problème depuis août 2010, donc je doute que cela change.

69voto

Cipi Points 5228

En JavaScript, il est possible de vérifier si deux chaînes de caractères ont la même valeur que des entiers :

  • "A" < "B"
  • "A" == "B"
  • "A" > "B"

Vous pouvez donc créer votre propre fonction qui vérifie les chaînes de caractères de la même manière que la fonction strcmp() .

Il s'agit donc de la fonction qui fait la même chose :

function strcmp(a, b)
{   
    return (a<b?-1:(a>b?1:0));  
}

14 votes

Encore une fois, lisez la question originale ! Il s'agit d'éviter de faire plus d'une comparaison de chaînes de caractères.

15 votes

Oh, désolé. Je n'avais pas vu ça... Au moins ça marche pour quelqu'un. =|

13voto

Gumbo Points 279147

Vous pouvez utiliser les opérateurs de comparaison pour comparer des chaînes de caractères . A strcmp pourrait être définie comme suit :

function strcmp(a, b) {
    if (a.toString() < b.toString()) return -1;
    if (a.toString() > b.toString()) return 1;
    return 0;
}

Editer Voici une fonction de comparaison de chaînes de caractères qui prend au maximum min { length( a ), la longueur ( b ) } pour déterminer la relation entre deux chaînes de caractères :

function strcmp(a, b) {
    a = a.toString(), b = b.toString();
    for (var i=0,n=Math.max(a.length, b.length); i<n && a.charAt(i) === b.charAt(i); ++i);
    if (i === n) return 0;
    return a.charAt(i) > b.charAt(i) ? -1 : 1;
}

11 votes

Mais cette routine fait exactement ce que le PO ne veut pas faire : il y a deux comparaisons de chaînes de caractères (sans parler des appels à la fonction "toString").

1 votes

@Pointy : Ce n'est pas possible avec une seule comparaison. Il faut au moins min { a.length , b.length } (comparer deux caractères à la fois) pour déterminer si les chaînes sont égales ou non. (Même localeCompare le fera en interne).

1 votes

Non, localeCompare ne le fera pas en interne. La comparaison des caractères est implémentée comme une soustraction, donc dès qu'il y a un résultat non nul de cette opération, vous connaissez la réponse. Votre réponse peut recomparer éventuellement todos les caractères de chaque chaîne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X