2010-12-03 10 views
15

Quiero utilizar una estructura de datos en JavaScript que se puede usar para almacenar el número de ID. Debería poder verificar si ya existe una clave en ese conjunto, algo así como Java Sets.¿Hay una estructura de datos como el conjunto de Java en JavaScript?

Quiero achive mismos comportamientos de la siguiente manera (esto es el código de Java):

Set<String> st = new HashSet<String>(); 
//add elemets 

if(st.contains("aks")){ 
    //do something 
} 

Quiero un JavaScript/dojo equivalente del código de seguridad.

Respuesta

0

Posiblemente con una matriz asociativa/Hashtable/dictionary (no sé cómo se llama exactamente), usando los elementos establecidos como claves y "cualquier otra cosa" como valores.

insert: mySet[key] = "Whatever"; 

delete: mySet[key] = null; 

check: if (mySet[key] != null) { ... } 
+0

gracias por responder. Pero ¿cómo puedo comprobar si contiene una clave? – aks

+0

quiero lograrlo en javascript – aks

+0

Ver la última edición, intenté aclarar. –

11

Por qué no utilizar un objeto normal y comprobar si existe una clave con JavaScript de hasOwnProperty?

var x = {}; 
x['key'] = 'val'; 
x.hasOwnProperty('key'); // true // 
x.hasOwnProperty('key2'); // false // 

Y aquí es un caso de uso más avanzada:

var x = {}; 
var prefix = 'item_'; 
for(var i=0;i<10;i++){ 
    x[prefix+i] = 'value '+(i+1); 
} 
x.hasOwnProperty('item_6'); // true // 
x.hasOwnProperty('other key'); // false // 

la eliminación de elementos se puede hacer así:

delete x['key']; 
+0

gracias por responder: quiero agregar dinámicamente muchas claves primero para objetar, luego deseo verificar si existe una clave en el objeto. ¿Cómo puedo hacer eso? – aks

+0

@Las claves pueden ser cualquier cadena (incluso una variable que contiene una cadena). Voy a actualizar con un ejemplo. –

+0

puedo hacer esto: var key1 = "xyz"; x [key1] = "val"; y luego verificar usando el código ur – aks

0

Hash es buen candidato para la implementación de Set. Se puede crear un conjunto utilizando una función de esa manera:

function set() { 
    var result = {}; 
    for (var i = 0; i < arguments.length; i++) result[arguments[i]] = true; 
    return result; 
} 

Por ejemplo:

x = set([1,2,2,4]) 
x[1] #==> true 
x[3] #==> false 
x[5] = true; # add element to the set 
x[5] = false; # remove element from the set 
0

conjuntos no tienen llaves. Solo tienen un conjunto de valores, pero los mapas tienen pares de entidades clave/valor.

Como resultado, tiene 2 opciones. Cada uno de ellos tiene sus inconvenientes y ventajas:

  1. Se puede utilizar como se describe anteriormente objeto de JavaScript. En realidad, es un mapa/matriz asociativa/tabla hash. Una de sus ventajas: puede garantizar con este tipo de estructura que las teclas son elementos únicos. Su inconveniente está relacionado con el problema: debe mantener cierta información adicional que no necesita en absoluto. Valores de mapas. trues o algunos otros valores. No importa. ¿Por qué los necesitas?

  2. Para resolver la desventaja anterior, puede considerar el uso de matrices de JavaScript. Pero tendrá que escribir algunos envoltorios para que el comportamiento de los arreglos se vea como el comportamiento de los conjuntos. Además, las operaciones que buscarán por uniqueId serán más lentas que las mismas para hashtables, ya que tendrás que iterar a través de todos los elementos de una matriz.

Por lo tanto, creo que se debe preferir tablas hash a las matrices, los ejemplos se pueden encontrar en otros puestos. Pero probablemente debas considerar cambiar tu estructura de datos. no mantenga uniqueId como claves con valores de destraba si es posible. Deje que sus identificadores únicos apunten a algunos objetos reales para los que se usan estos identificadores únicos.

PD: una cosa más. Las matrices también son objetos en realidad. Como resultado, pueden usarse también como tablas/mapas.

20

He escrito una aplicación JavaScript HashSet que hace lo que quiere y permite que cualquier objeto a ser un miembro del conjunto: http://code.google.com/p/jshashtable

Sin embargo, si sólo necesita almacenar cadenas, se podría hacer algo más simple almacenando los miembros del conjunto como nombres de propiedad de un Objeto normal. Por ejemplo:

function StringSet() { 
    var setObj = {}, val = {}; 

    this.add = function(str) { 
     setObj[str] = val; 
    }; 

    this.contains = function(str) { 
     return setObj[str] === val; 
    }; 

    this.remove = function(str) { 
     delete setObj[str]; 
    }; 

    this.values = function() { 
     var values = []; 
     for (var i in setObj) { 
      if (setObj[i] === val) { 
       values.push(i); 
      } 
     } 
     return values; 
    }; 
} 

Una nota acerca de la aplicación: val es un objeto utilizado internamente por la aplicación StringSet que es único para cada conjunto. La comparación de los valores de propiedad del objeto cuyos nombres de propiedad constituyen el conjunto (setObj) contra val elimina la necesidad de una verificación hasOwnProperty() y garantiza que solo las cadenas que se hayan agregado al conjunto aparecerán en values.

Ejemplo de uso:

var set = new StringSet(); 
set.add("foo"); 
set.add("bar"); 

alert(set.contains("foo")); // true 
alert(set.contains("baz")); // false 

set.values(); // ["foo", "bar"], though not necessarily in that order 
set.remove("foo"); 
set.values(); // ["bar"] 
+1

¿Cuál es el propósito de evitar la llamada a hasOwnProperty()? ¿Es más rápido el control de igualdad? Si es así, ¿cómo lo sabes? –

+0

@ JørgenFogh: sospecho que la comprobación de igualdad es probable que sea más rápida porque evita la sobrecarga de una llamada a función. No he probado esto, así que siéntete libre de crear un punto de referencia; Me interesaría ver los resultados. –

+0

@ JørgenFogh: La otra ventaja de la comparación de objetos es que no hay forma de que pueda salir mal. –

4

No se necesita ir de discotecas, esto es nativa de Javascript. Usa objetos Parece que solo necesitas las llaves, no los valores. La búsqueda es un tiempo constante.

var st = {'aks':1, 'foo':1, 'bar':1}; // or could start with empty {}. 1 could be any value of any type, it's just short. 

//add elements 
st.baz = 1; 

//or load up dynamically 

myArrayOfStrings.forEach(function(key){ 
st[key] = 1; 
}); 


if("aks" in st){ 
    //do something 
} 
+0

'forEach' no es compatible con IE. Esto también necesita una comprobación 'hasOwnProperty()' en caso de que algún otro código haya hecho algo como 'Object.prototype.aks = 1'. –

+0

Sí, en mi ejemplo asumo ES5 y que nadie está modificando el prototipo de objeto, lo cual es una buena práctica. – peller

Cuestiones relacionadas