2012-05-07 11 views
7

Supongamos que desea verificar qué cadena de entrada ha ingresado un usuario en un campo de formulario. ¿Cuál sería la forma más rápida de verificar esta entrada con una lista de valores posibles?Rendimiento de la operación OR (||) frente a inArray()

Los siguientes ejemplos usan jQuery.

Primer método: utilizando ||

if (input == "firstValue" || input == "secondValue" || ...) { 
    ... 
} 

Segundo método: Usando inArray()

if ($.inArray(input, array) >= 0) { 
    ... 
} 

¿Hay diferencias significativas entre estos dos métodos?

+3

tienen la complejidad O (n) del peor caso, donde n es la cantidad de cosas que está probando, la única ganancia de rendimiento sería una no es una llamada a función, mientras que la otra sí lo es. –

+2

¿Es esto realmente JavaScript de lo que estás hablando? – Niko

+0

En un nivel práctico, sin embargo, me inclinaría hacia algo como 'inArray()' más solo por el hecho de que tiene un mayor potencial para ser dinámico para grandes conjuntos de datos de contracheck. Además de ser más fácil de leer. ¡Imagínense si tuviéramos 10 o más valores para contraatacar! : D –

Respuesta

17

No desea la manera más rápida pero más legible. Y eso es in_array() (JavaScript: array.indexOf(value) >= 0) para más de 2 o 3 valores. La diferencia de rendimiento es insignificante: mientras que una llamada a función y creación de matriz ciertamente tiene cierta sobrecarga, no importa si se compara con costosas operaciones como acceso a archivos, acceso a bases de datos, acceso a la red, etc. Por lo tanto, al final, nadie notará la diferencia.

He aquí una breve benchmark, cada uno con 1 millón de iteraciones:

5.4829950332642 - in_array, the array is recreated everytime 
2.9785749912262 - in_array, the array is created only once 
0.64996600151062 - isset(), the array way created only once and then the values were turned to keys using array_flip() 
2.0508298873901 - || 

Por lo tanto, el más rápido, pero aún así es muy fácil de leer esto. A menos que cree $arr solo una vez y úselo muchas veces, no es necesario y simplemente puede quedarse con in_array().

$arr = array_flip(array('your', 'list', 'of', 'values')); 
if(isset($arr[$value])) ... 

En caso de que qué pide JavaScript (! En este caso deshacerse de esas $ prefijos), la mejor solución es utilizar Array.indexOf():

['a', 'b', 'c'].indexOf(value) >= 0 

Sin embargo, no todos los navegadores ya son compatibles con Array.indexOf(), por lo que es posible que desee utilizar, por ejemplo la función de Underscore.js:

_.contains(['a', 'b', 'c'], value) 

jQuery también tiene una función para esto:

$.inArray(value, ['a', 'b', 'c']) 

La forma más rápida sería con un objeto y el operador in, pero la definición del objeto es menos legible que la matriz definición:

value in {'a':0, 'b':0, 'c':0} 

Aquí hay un punto de referencia JSPerf para las diversas soluciones: http://jsperf.com/inarray-vs-or - pero de nuevo, en lugar de la b La diferencia de rendimiento ig es insignificante en la mayoría de los casos, ya que no va a ejecutar el código millones de veces en un bucle.

+0

+1 el poder de la respuesta breve y concisa –

+0

En mi humilde opinión, es mejor ajustar 'Array.indexOf()' que incluir otra biblioteca JS completa ... – Alnitak

+1

Esa es una buena idea si todo el código está escrito por usted y no se considera heredado código - si usa 'for (var i in array)' en alguna parte (que no debería), extender 'Array.prototype' romperá estos bucles. Además de eso, el OP ya está usando jQuery. – ThiefMaster

4

La respuesta es, que depende ...

Si hay sólo unas pocas posibilidades, utilizar if (a || b || c).

Si hay quizá hasta 10, utilice Array.indexOf()

Tenga en cuenta que para las dos recomendaciones anteriores, la elección debe depender de la legibilidad y no realmente en el rendimiento.

Si hay (muchos) más que eso, utilice un Object con las claves iguales a los valores, entonces puede usar if (myVar in myKeyObj). Esto debería dar el peor rendimiento O(log n).

+0

Creo que etiquetó incorrectamente la pregunta. Su código es PHP, no JavaScript. – ThiefMaster

+0

@ThiefMaster doh! Entonces es ... – Alnitak

+0

@ThiefMaster ¿por qué crees que es PHP? ¿Por el hecho de que usa el prefijo del dólar? :) habiendo dicho eso, él confía en el resultado booleano de inArray ... man esto es confuso –

2

El rendimiento generalmente no es un gran problema cuando se hace javascript, y por lo general son preguntas difíciles de responder.

En esta muestra, la diferencia clave entre las soluciones es la escala. La primera solución siempre hará una cantidad predeterminada de comparaciones, la solución inArray escala peor porque se comparará más si hay más valores.

Sin embargo, yo todavía iría con Array, el 99,99% de probabilidad de rendimiento realmente no importa. Desea mantener su código mantenible, eso es más importante.

+0

'La primera solución siempre hará una cantidad predeterminada de comparaciones', pensé que javascript/php saldría antes si se cumple en cualquiera de los' || '? –

+0

Cierto, entonces se conocerá el máximo. – TJHeuvel

+0

Ahh, ahora veo lo que quieres decir con "predeterminado". Gracias –

2

En la mayoría de los idiomas InArray() se implementa como esto:

function inArray(needle, haystack) { 
    for (i = 0; i < length; i++) { 
    if (haystack[index] == needle) { 
     return true; 
    } 
    } 

    return false; 
} 

Si se va a desenrollar ese bucle, que terminarías haciendo

if (haystack[0] == needle) { 
    return true; 
} 
if (haystack[1] == needle) { 
    return true; 
} 
if (haystack[3] == needle) { 
    return true; 
} 
// and so on 

que podría ser condensado a

if (haystack[0] == needle || haystack[2] == needle || …) { 
    return true; 
} 

sin cambiar lo que está sucediendo debajo del capó.


Si repetidamente tiene que buscar cosas así, le sugiero que conozca mapas. en lugar de

var haystack = ['hello', 'world', 'how', 'is', 'life']; 
if (inArray("life", haystack)) { 
    // … 
} 

hacer

var haystack = {'hello' : true, 'world' : true, 'how' : true, 'is' : true, 'life' : true}; 
if (haystack["life"]) { 
    // … 
} 

Los más elementos tienen que comprobar en contra, mejor será el mapa llevará a cabo en comparación con la matriz.

+0

¿Percibiría una mejora en el rendimiento? si necesito verificar, por ejemplo, menos de 100 elementos? – user1301428

+0

http://jsperf.com/map-or-array muestra que con 10 elementos en Array() es más rápido, pero con 26 elementos más lentos que inMap(). Tenga en cuenta que el rendimiento de inArray() se correlaciona con el número de elementos en la matriz y la posición de un elemento si se puede encontrar. inMap() por otro lado tiene el mismo rendimiento independientemente de los elementos para comparar. – rodneyrehm

+0

bien, entonces Chrome no está de acuerdo con Firefox en Array() con 10 elemens siendo más rápidos. Debería obtener la imagen de todos modos ... – rodneyrehm

Cuestiones relacionadas