2010-01-30 6 views
293

J'essaie d'optimiser une fonction qui fait une recherche binaire de chaînes en Javascript.Comment comparer les chaînes de caractères de manière optimale?

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

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

Existe-t-il une telle fonction native dans Javascript, qui peut renvoyer une valeur ternaire afin qu'une seule comparaison soit requise dans chaque itération de la recherche binaire?

+5

'retour str1 str2; '? –

+1

@ 1 "Ce n'est pas optimal, il faut deux comparaisons de chaînes – HRJ

+3

C'est encore un ordre de grandeur (!) Plus rapide que' localeCompare() 'sur ma machine @ Le custom strcmp()' de Gumbo peut être plus rapide, selon l'optimisation l'implémentation interne des comparaisons d'égalité pour les chaînes est –

Répondre

390

Vous pouvez utiliser la méthode localeCompare().

string_a.localeCompare(string_b); 

/* Expected Returns: 

0: exact match 

-1: string_a < string_b 

1: string_a > string_b 

*/ 

Lectures complémentaires:

+11

Malheureusement, stringCompare n'est pas fiable. Opera, IE, Firefox, Chrome et Safari renvoient tous 1 pour 'dog'.localeCompare (' cat '), ce qui est à prévoir, et -1 lorsque vous inversez l'appelant et l'argument. būt lettres majuscules se comportent oddly- 'dog'.localeCompare (' Dog ') des navigateurs je testés, seuls 4 Safar retour 1. Les Il renvoie -1 dans IE8 et Firefox 3, et Opera 9 et Les deux Chrome retournent +32. – kennebec

+18

Vous pouvez utiliser toLowerCase ou toLocaleLowerCase lorsque vous souhaitez des comparaisons insensibles à la casse. – Fabrice

+2

Je pense qu'il est important de noter que V8 (Chrome) semble interpréter ECMA-262 différemment de IE/Firefox sur localeCompare. Par exemple: "a" .localeCompare ("Z") devrait renvoyer -1 mais retourne 7 qui est le code de charte de "a" - charcode de "Z". Malheureusement, le langage dans la spécification est lâche, en spécifiant que localeCompare() renvoie un nombre négatif, un nombre positif ou 0. (Notamment -1, 1, 0). J'ai déposé un rapport de bug dans l'espoir que cela pourrait changer, mais c'est un problème depuis août 2010, donc j'en doute. – JoshVarty

11

Vous pouvez use the comparison operators to compare strings. Une fonction strcmp pourrait être définie comme ceci:

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

Modifier est ici une fonction de comparaison de chaîne qui prend au plus min {longueur (un), longueur (b)} comparaisons dire comment deux chaînes se rapportent les uns aux autres:

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; 
} 
+6

Mais cette routine fait exactement ce que l'OP ne veut pas faire: il y a deux comparaisons de chaîne (et encore moins les appels de fonction à ") toString "). – Pointy

+0

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

+0

Non, localeCompare ne le fera pas en interne. La comparaison des caractères est implémentée comme une soustraction, donc dès que le résultat de cette opération est différent de zéro, vous connaissez la réponse. Votre réponse peut re-comparer éventuellement * tous * les caractères de chaque chaîne. – Pointy

41

Bien en JavaScript, vous pouvez vérifier deux chaînes pour les valeurs mêmes que les entiers afin yo peut faire:

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

Et vous pouvez donc faire votre propre fonction qui vérifie la même manière enfile comme strcmp().

Ce serait donc la fonction qui fait la même chose:

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

Encore une fois, lisez la question originale !! Le but est d'éviter de faire plus d'une comparaison de chaînes. – Pointy

+7

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

+14

vous voulez dire "A" == "B"? – lex82