Saltar al contenido

¿Cuál es la forma más rápida de comparar cadenas en JavaScript?

Esta reseña ha sido evaluado por especialistas para asegurar la exactitud de nuestro tutorial.

Solución:

Comparando cadenas con a === b es la forma más rápida de comparar string nativos.

Sin embargo, si pudiera crear objetos de cadena como new String("test"), reutilizarlos y usarlos en las comparaciones, eso sería aún más rápido, porque el motor JS solo necesitaría hacer una comparación de punteros, que es (una pequeña cantidad) más rápida que string comparaciones.

Ver http://jsperf.com/string-contra-comparaciones-de-objetos

Si su “hacer algo” comparte un formulario similar con diferentes valores, puede poner los valores en un mapa y usar el string como un key. Por ejemplo, imagina que tienes que procesar muchos números con diferentes unidades de longitud y quieres convertirlos todos a metros:

var conversionToMeters = 
    "inch":   0.0254,
    "inches": 0.0254,
    "foot": 0.3048,
    "feet": 0.3048,
    "cubit":  0.4572,
    "cubits": 0.4572,
    "yard":  0.9144,
    "yards": 0.9144,
    "kilometer":  1000,
    "kilometers": 1000,
    "mile":  1609.344,
    "miles": 1609.344,
    "lightyear":  9.46e15,
    "lightyears": 9.46e15,
    "parsec":  3.09e16,
    "parsecs": 3.09e16,

(Las abreviaturas (como “km”) y la ortografía internacional (como “kilómetros”) se omiten por motivos de brevedad. Puede preparar ese mapa con anticipación para evitar la creación de sobrecarga. Ahora, dada una variable length tal como length = "80 miles", tu puedes hacer:

var magnitude = length.replace(/[D]/g, "");
var unit = length.replace(/[ds]/g, "");
var lengthInMeters = magnitude * conversionToMeters[unit];
alert(lengthInMeters + " meters"); // Ta-da!

Si su “hacer algo” no comparte un código común, aún puede usar un mapa, pero será un mapa de funciones:

var actions = 
    "eat": function() 
        if (spareFood > 0) 
            spareFood--;
            energy += 10;
            health++;
            alert("Yum!");
        
    ,
    "walk": function() 
        if (energy > 0) energy--;
        // ...
    ,
    "attack": function() 
        if (energy > 0) 
            if (Math.random() < 0.25) 
                health--;
                alert("Ouch!");
            
            energy--;
        
    ,
    // ...
;

Este es un ejemplo un poco tonto, pero espero que explique la idea básica. Las acciones también pueden ser etiquetas XML, o nombres de instrucciones de CPU en una máquina virtual, o nombres de productos que tienen requisitos de envío especiales, o lo que sea. Una vez que tengas tu action variable, ejecutarla es tan simple como:

actions[action]();

Un mapa no es la única forma de hacer este tipo de cosas. Su ejemplo original de if / else se puede optimizar fácilmente anidando los ifs dentro de ifs adicionales que son diseñado para eliminar rápidamente la mayoría de las cadenas candidatas.

Los criterios en los que se ramifique dependerán de las cadenas exactas con las que esté trabajando. Podría ser la longitud del string, o la primera letra, o un par de las letras más distintivas:

if (str.length === 3) 
    // test all length 3 strings here
    if (str === strA) doSomething();
    else if (str == strB) doSomething();
 else if (str.length === 4) 
    // test all length 4 strings here
    if (str === strC) doSomething();
    else if (str === strD) doSomething();

O:

var first = str[0]; // first character
if (first >= "0" && first <= "9") {
    // test all strings that start with digits here
if (first >= "a" && first <= "l") 
    // test all strings that start with letters
    // in the first half of the alphabet here
 else if (first >= "m" && first <= "z") 
    // test all strings that start with letters
    // in the latter half of the alphabet here

Puede anidar este tipo de pruebas unas dentro de otras hasta el grado que sea apropiado para filtrar las cadenas particulares con las que está trabajando. Esta es una especie de búsqueda binaria desenrollada, aunque los criterios en los que se ramifica no tienen que dividir las cadenas candidatas en exactamente dos grupos.

Además, cuando usa un if / elseif como este, a menudo vale la pena organizar las cadenas en orden descendente de frecuencia. Es decir, primero pruebe los que más le sucedan. Si solo hay un par de cadenas que componen la mayoría de los datos, llévelas a la parte superior e incluso colóquelas fuera de las pruebas previas basadas en la longitud o la primera letra.

Tendrá que decidir si vale la pena hacer estas cosas: si lleva estas técnicas al extremo, es posible que pueda obtener pequeños beneficios de rendimiento adicionales, pero sacrificará la legibilidad y la capacidad de mantenimiento.

PD: No conozco JavaScript lo suficientemente bien como para saber exactamente cómo funcionarán estas técnicas, pero he hecho cosas similares en Java. En Java, el enfoque del mapa es inmejorable cuando el "hacer algo" requiere valores diferentes pero puede usar el mismo código. En un programa diferente, necesitaba switch en un valor entero realizando alrededor de 400 acciones diferentes (fue horrible). La VM del cliente HotSpot tiene una implementación pésimamente ineficiente del switch declaración que es simplemente un montón de elseifs, y fue demasiado lenta. Un array de funciones (que técnicamente eran objetos con métodos virtuales anulados) era más rápido, pero la sobrecarga de llamadas de función era demasiado grande en comparación con la simplicidad de cada acción. En este caso encontré un mixed búsqueda binaria-cuaternaria para que sea eficaz. Lo que eso significa es: las pruebas externas fueron if / elses que dividieron los valores de entrada de manera uniforme en dos grupos. Estos se anidaron hasta que solo quedaron cuatro valores posibles en los grupos internos. Luego utilicé un if / elseif / elseif / else para distinguir entre los cuatro valores restantes. Como esto era tan largo, escribí un código para escribirlo por mí, pero aún así valió la pena el esfuerzo para esta aplicación en particular.

PPS Hay un enfoque que omití anteriormente, pero lo incluiré para que esté completo: si sus cadenas rara vez necesitarán cambiarse, puede usar una función hash perfecta. Hay programas de utilidad que diseñan estas funciones para usted: simplemente proporcióneles una lista de todas sus cadenas. Una función hash perfecta calculará un código hash entero a partir de un stringy garantice que no hay dos cadenas de su conjunto que tengan el mismo código hash. Luego puede usar el código hash entero para buscar la acción en un array. Es útil para cosas como analizar palabras clave de lenguajes de programación. Puede ser más rápido en un lenguaje más cercano al metal, pero en JavaScript sospecho que no valdrá la pena. Lo estoy mencionando por si acaso.

Comentarios y valoraciones del tutorial

Puedes animar nuestro cometido añadiendo un comentario o valorándolo te estamos eternamente agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *