2011-04-24 6 views
45

tengo algunos datos que me originalmente almacenada en un objeto genérico Javascript, con la identificación como una clave:¿Cómo mantener un objeto/arreglo de Javascript ordenado al tiempo que se mantienen las búsquedas clave?

{ 
    "7": {"id":"7","name":"Hello"}, 
    "3": {"id":"3","name":"World"}, 
    ... 
} 

Sin embargo, he descubierto que los navegadores no garantizan un orden determinado objeto, cuando un bucle a través de ellos, por lo que en el "3" anterior vendría antes de "7". I cambiado a usar un formato de matriz de esta manera:

[ 
    {"id":"7","name":"Hello"}, 
    {"id":"3","name":"World"}, 
    ... 
] 

Ahora, puedo bucle en el orden correcto, pero no puede hacer búsquedas rápidas, por ejemplo, data["3"] sin tener que recorrer el conjunto.

¿Hay una buena manera de combinar ambos enfoques? Prefiero evitar el uso de un objeto separado para cada formato, porque el objeto es bastante grande (cientos de elementos).

+5

posible duplicado de [? Estructura de datos Javascript para la búsqueda rápida y ordenada bucle] (http://stackoverflow.com/questions/3549894/javascript-data-structure-for-fast-lookup-and-ordered-looping) –

+0

No estoy seguro de que haya una forma mejor de lograr esto que la respuesta a la que me he vinculado. Rompe tu objetivo de evitar objetos separados para cada uno, ¡pero me encantaría saber una mejor manera! :) –

Respuesta

61

Me he encontrado con este problema también. Una solución es mantener una matriz ordenada de claves además del objeto original.

var objects = { 
    "7": {"id":"7","name":"Hello"}, 
    "3": {"id":"3","name":"World"}, 
    ... 
} 
var order = [ "3", "7", ... ]; 

Ahora bien, si desea que el segundo elemento se puede hacer esto de búsqueda:

var second_object = objects[order[1]]; 

El estándar ECMA no dice nada sobre el orden de los elementos en un objeto. Y específicamente, Chrome reordena las claves cuando se se parecen a los números. Ejemplo:

var example = { 
    "a": "a", 
    "b": "b", 
    "1": "1", 
    "2": "2" 
}; 

si imprime esto en Chrome obtener algo como:

{ 
    1: "1", 
    2: "2", 
    "a": "a", 
    "b": "b" 
}; 

Es un poco amargo .. pero la vida.

También podría usar la solución enlazada a Andy, básicamente envolviendo estas dos juntas en un solo objeto.

Una alternativa que uso mucho es una función de mapa personalizada que le permite especificar el orden en que se atraviesa el objeto. Por lo general, hará la ordenación cuando imprima sus datos para el usuario, de modo que mientras hace un bucle y crea las filas de su tabla (por ejemplo) su iterador pasará las filas en el orden especificado por su función de clasificación. Pensé que era una buena idea :)

La firma se parece a:

function map(object, callback, sort_function); 

Ejemplo de uso:

map(object, function (row) { 
    table.add_row(row.header, row.value); 
}, function (key1, key2) { 
    return object[key1] - object[key2]; 
}); 
+0

¡Gran idea, gracias! De hecho, hice lo contrario de lo sugerido y guardé el almacenamiento de datos principal como una matriz (para un mejor bucle), luego almacené los índices de la matriz en un objeto, generado sobre la marcha. – DisgruntledGoat

+0

¿No sería más fácil simplemente asignar los valores a los índices con un ciclo normal para (var i; i MJB

Cuestiones relacionadas