2008-11-21 16 views
10

Tengo un grupo de cadenas en Javascript y necesito escribir una función que detecta si otra cadena específica pertenece a este grupo o no.manera más rápida de detectar si un valor está en un grupo de valores en Javascript

¿Cuál es la manera más rápida de lograr esto? ¿Está bien poner el grupo de valores en una matriz y luego escribir una función que busque a través de la matriz?

Creo que si mantengo los valores ordenados y hago una búsqueda binaria, debería funcionar lo suficientemente rápido. ¿O hay alguna otra forma inteligente de hacerlo, que puede funcionar más rápido?

Respuesta

16

utiliza una tabla hash, y hacer esto:

// Initialise the set 

mySet = {}; 

// Add to the set 

mySet["some string value"] = true; 

... 

// Test if a value is in the set: 

if (testValue in mySet) { 
    alert(testValue + " is in the set"); 
} else { 
    alert(testValue + " is not in the set"); 
} 
+1

Usar el operador "in" es probablemente la forma más elegante de hacerlo. +1 – Tomalak

+0

Mientras trataba de bailar alrededor de AngularJS 'ng-if, se me ocurrió esta sintaxis (justo después de leer esta respuesta): '({value1: 1, value2: 1}) [' value2 ']' - self- prueba de mapa contenido. –

0

Usar una tabla hash podría ser una opción más rápida.

Independientemente de la opción que elija, vale la pena probar su rendimiento frente a las alternativas que considera.

7

Puede utilizar un objeto de esta manera:

// prepare a mock-up object 
setOfValues = {}; 
for (var i = 0; i < 100; i++) 
    setOfValues["example value " + i] = true; 

// check for existence 
if (setOfValues["example value 99"]); // true 
if (setOfValues["example value 101"]); // undefined, essentially: false 

Esto se aprovecha del hecho de que los objetos se implementan como matrices asociativas. Lo rápido que eso depende de sus datos y la implementación del motor de JavaScript, pero puede hacer algunas pruebas de rendimiento fácilmente para compararlas con otras variantes de hacerlo.

Si un valor puede aparecer más de una vez en su conjunto y la "frecuencia" es importante para usted, también puede usar un número creciente en lugar del booleano que utilicé para mi ejemplo.

+0

Esto no funciona. setOfValues ​​[x] donde x no está en el conjunto no se evaluará como indefinido, producirá un error. Lo que quiere es: "x en setOfValues" para probar la membresía. –

+0

Se evaluará como indefinido. No dará lugar a un error. Pruébalo. – Tomalak

0

Depende de la cantidad de valores que haya.

Si hay algunos valores (menos de 10 a 50), la búsqueda a través de la matriz puede estar bien. Una tabla hash puede ser excesiva.

Si tiene muchos valores, una tabla hash es la mejor opción. Requiere menos trabajo que ordenar los valores y hacer una búsqueda binaria.

+0

pensé que todo en JS era una tabla hash, un arry es solo 0 => firstentry, 1 => secondentry ¿no? –

+0

@Trull: lo dudo. Array es diferente de Object, y probablemente optimizado para el rendimiento, aunque dependerá de la implementación. – PhiLho

5

Un comentario a la mencionada soluciones de patata. En realidad, {} crea un objeto (también mencionado anteriormente) que puede provocar algunos efectos secundarios. Uno de ellos es que su "hash" ya está rellenado previamente con los métodos de objetos predeterminados.

Así "toString" in setOfValues será true (al menos en Firefox). Puedes anteponer otro personaje, p. "." a sus cadenas para evitar este problema o usar el objeto Hash proporcionado por la biblioteca "prototipo".

+2

Gracias por notar esto. Otra razón más para odiar JavaScript. –

2

Una forma posible, especialmente eficaz si el conjunto es inmutable, pero todavía se puede utilizar con un conjunto de variables:

var haystack = "monday tuesday wednesday thursday friday saturday sunday"; 
var needle = "Friday"; 
if (haystack.indexOf(needle.toLowerCase()) >= 0) alert("Found!"); 

Por supuesto, es posible que tenga que cambiar el separador en función de las cuerdas tienes que poner allí ...

Una variante más robusta puede incluir límites para asegurar ni "día casó" ni "día" puede coincidir positivamente:

var haystack = "!monday!tuesday!wednesday!thursday!friday!saturday!sunday!"; 
var needle = "Friday"; 
if (haystack.indexOf('!' + needle.toLowerCase() + '!') >= 0) alert("Found!"); 

podría no ser necesario si la entrada es segura (ej. fuera de la base de datos, etc.).

Lo usé en un script de Greasemonkey, con la ventaja de usar el pajar directamente fuera del almacenamiento de GM.

3

Tropezamos con esto y nos dimos cuenta de que las respuestas no están actualizadas. En este día y edad, no debería implementar conjuntos utilizando hashtables excepto en casos de esquina. Debe usar sets.

Por ejemplo:

> let set = new Set(); 
> set.add('red') 

> set.has('red') 
true 
> set.delete('red') 
true 
> set.has('red') 
false 

se refieren a este SO publicar para más ejemplos y discusión: Ways to create a Set in JavaScript?

0

Sé que es un antiguo puesto. Sin embargo, para detectar si un valor está en un conjunto de valores que puede manipular a través de gama indexOf() la que busca y detecta el presente del valor

var myString="this is my large string set"; 
 
var myStr=myString.split(' '); 
 
console.log('myStr contains "my" = '+ (myStr.indexOf('my')>=0)); 
 
console.log('myStr contains "your" = '+ (myStr.indexOf('your')>=0)); 
 

 
console.log('integer example : [1, 2, 5, 3] contains 5 = '+ ([1, 2, 5, 3].indexOf(5)>=0));

Cuestiones relacionadas