Tengo un modelo con posiblemente miles de objetos. Me preguntaba cuál sería la forma más eficiente de almacenarlos y recuperar un solo objeto una vez que tengo su id. Los id's son números largos.
Así que estas son las 2 opciones que estaba pensando. en la opción uno es una matriz simple con un índice incremental. en la opción 2 es una matriz asociativa y tal vez un objeto, si hace una diferencia. Mi pregunta es cuál es más eficiente, cuando la mayoría de las veces necesito recuperar un solo objeto, pero también a veces bucle a través de ellos y ordenar.
Opción uno con array no asociativo:
var a = [{id: 29938, name: 'name1'},
{id: 32994, name: 'name1'}];
function getObject(id) {
for (var i=0; i < a.length; i++) {
if (a[i].id == id)
return a[i];
}
}
Opción dos con array asociativo:
var a = []; // maybe {} makes a difference?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
return a[id];
}
Actualización:
OK, entiendo que el uso de una matriz en la segunda opción está fuera de la cuestión. Así que la línea de declaración de la segunda opción en realidad debería ser: var a = {};
y la única pregunta es: qué funciona mejor para recuperar un objeto con un id dado: un array o un objeto donde el id es la clave.
y también, ¿cambiará la respuesta si tengo que ordenar la lista muchas veces?
La versión corta: Las matrices son más rápidas que los objetos. Pero no hay una solución 100% correcta.
var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];
var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};
var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};
for (var f = 0; f < 2000; f++) {
var newNo = Math.floor(Math.random()*60000+10000);
if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
a1.push({id: newNo, name: 'test'});
}
Hay algunos conceptos erróneos en su pregunta.
Estos son arrays:
var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";
Esto también es una matriz:
var a3 = [];
a3[29938] = "a";
a3[32994] = "b";
Básicamente es un array con agujeros, porque todos los arrays tienen indexación continua. Es más lento que los arrays sin agujeros. Pero iterar manualmente a través de la matriz es aún más lento (en su mayoría).
Esto es un objeto:
var a3 = {};
a3[29938] = "a";
a3[32994] = "b";
He aquí una prueba de rendimiento de tres posibilidades:
Una excelente lectura sobre estos temas en Smashing Magazine: Writing fast memory efficient JavaScript
En realidad, no se trata de una cuestión de rendimiento, ya que las matrices y los objetos funcionan de forma muy diferente (o se supone que lo hacen, al menos). Los arrays tienen un índice continuo 0..n
, mientras que los objetos asignan claves arbitrarias a valores arbitrarios. Si quieres proporcionar claves específicas, la única opción es un objeto. Si no te importan las claves, es un array.
Si intentas establecer claves arbitrarias (numéricas) en un array, realmente tienes una pérdida de rendimiento, ya que el array rellenará todos los índices intermedios:
> foo = [];
[]
> foo[100] = 'a';
"a"
> foo
[undefined, undefined, undefined, ..., "a"]
(Ten en cuenta que el array no contiene realmente 99 valores inexistentes
, pero se comportará de esta manera ya que [se supone que estás] iterando el array en algún punto.)
Los literales de ambas opciones deberían dejar muy claro cómo se pueden utilizar:
var arr = ['foo', 'bar', 'baz']; // no keys, not even the option for it
var obj = { foo : 'bar', baz : 42 }; // associative by its very nature
Intenté llevar esto a la siguiente dimensión, literalmente.
Dada una matriz de 2 dimensiones, en el que los ejes x e y son siempre la misma longitud, ¿es más rápido para:
a) buscar la celda creando una matriz bidimensional y buscando el primer índice, seguido del segundo índice, es decir
var arr=[][]
var cell=[x][y]
o
b) crear un objeto con una representación de cadena de las coordenadas x e y, y luego hacer una única búsqueda en ese obj, es decir
var obj={}
var cell = obj['x,y']
Resultado: Resulta que es mucho más rápido hacer dos búsquedas de índices numéricos en las matrices, que una búsqueda de propiedades en el objeto.
Resultados aquí: