2010-01-30 16 views
293

Estoy tratando de optimizar una función que realiza búsqueda binaria de cadenas en Javascript.¿La forma óptima de comparar cadenas en Javascript?

La búsqueda binaria requiere que usted sepa si la clave es == el pivote o < el pivote.

Pero esto requiere dos comparaciones de cadenas en Javascript, a diferencia de C como idiomas que tienen la función strcmp() que devuelve tres valores (-1, 0, +1) para (menor que, igual, mayor que).

¿Existe tal función nativa en Javascript, que puede devolver un valor ternario para que solo se requiera una comparación en cada iteración de la búsqueda binaria?

+5

'str1 retorno str2; '? –

+1

@ 1 "Eso no es óptimo; requiere dos comparaciones de cadenas. – HRJ

+3

Todavía es un orden de magnitud (!) Más rápido que' localeCompare() 'en mi máquina. @ Gumbo's custom' strcmp() 'puede ser más rápido, dependiendo de cuán optimizado la implementación interna de las comparaciones de igualdad para cadenas es. –

Respuesta

390

Puede usar el método localeCompare().

string_a.localeCompare(string_b); 

/* Expected Returns: 

0: exact match 

-1: string_a < string_b 

1: string_a > string_b 

*/ 

Lectura adicional:

+11

Desafortunadamente, stringCompare no es confiable. Opera, IE, Firefox, Chrome y Safari devuelven 1 para 'dog'.localeCompare (' cat '), que es de esperar, y -1 cuando invierte la llamada y el argumento. pero las cartas de capital se comportan oddly- 'dog'.localeCompare (' perro ') de los navegadores que he probado, sólo se volvió Safar 4 1. Devuelve -1 en IE8 y Firefox 3, y Opera 9 y Chrome ambos devuelven +32. – kennebec

+18

Puede usar toLowerCase o toLocaleLowerCase cuando desee comparaciones que no distingan entre mayúsculas y minúsculas. – Fabrice

+2

Creo que es importante tener en cuenta que V8 (Chrome) parece interpretar ECMA-262 de forma diferente a IE/Firefox en localeCompare. Por ejemplo: "a" .localeCompare ("Z") debería devolver -1, pero en su lugar devuelve 7, que es el código de "a" - código de "Z". Desafortunadamente, el lenguaje en la especificación es flexible, especificando que localeCompare() devuelve un número negativo, un número positivo o 0. (No específicamente -1, 1, 0). Archivé un informe de error con la esperanza de que esto cambie, pero ha sido un problema desde agosto de 2010, así que dudo que lo haga. – JoshVarty

11

Puede use the comparison operators to compare strings. Una función strcmp podría definirse así:

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

Editar Aquí es una función de comparación de cadenas que tiene como máximo min {longitud (un), longitud (b)} comparaciones para contar cómo dos cadenas se relacionan entre sí:

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

Pero esta rutina hace exactamente lo que el OP no quiere hacer: hay dos comparaciones de cadenas (y mucho menos esas llamadas de función a " Encadenar"). – Pointy

+0

@Pointy: no es posible con solo una comparación. Necesitas al menos pasos mínimos {'a.length',' b.length'} (compara dos caracteres a la vez) para determinar si las cadenas son iguales o no. (Incluso 'localeCompare' lo hará internamente.) – Gumbo

+0

No, localeCompare no lo hará internamente. La comparación de los caracteres se implementa como una resta, por lo que tan pronto como haya un resultado distinto de cero de esa operación, usted sabrá la respuesta. Su respuesta puede volver a comparar posiblemente * todos * los caracteres de cada cadena. – Pointy

41

Bueno, en JavaScript puede marcar dos cadenas para valores iguales a los enteros, de modo yo puede hacer esto:

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

Y por lo tanto, usted puede hacer su propia función que comprueba encadena la misma manera que la strcmp().

lo que esta sería la función que hace lo mismo:

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

De nuevo, ¡lea la pregunta original! El punto es evitar hacer más de una comparación de cuerdas. – Pointy

+7

Oh, lo siento. No vi eso ... Al menos esto funciona para alguien. = | – Cipi

+14

¿quieres decir "A" == "B"? – lex82

Cuestiones relacionadas