2011-03-10 14 views
24

que tienen una serie como esta (con poco más de 3000 objetos en lugar de los 3 aquí):¿Cuál es la mejor manera de consultar una matriz en javascript para obtener solo los elementos de ella que quiero?

items = [{name:'charlie', age:'16'}, {name:'ben', age:'18'}, {name:'steve', age:'18'}] 

¿Cuál es la mejor manera de devolver una matriz con sólo los objetos de las personas que son 18? Así que quiero:

items = [{name:'ben', age:'18'}, {name:'steve', age:'18'}] 

Lo mejor que puedo pensar es esta (usando jQuery):

newArray = [] 
$.each(items, function(index, item) { 
    if(item.age=='18') { 
     newArray.push(item) 
    } 
}) 

Teniendo en cuenta que hay 3.000 miles de objetos, y también que voy a estar haciendo que la comparación hasta cincuenta veces de una vez, eso es mucho bucle. ¿Hay una mejor manera?

+0

Para aclarar más, estoy creando esta matriz en la carga de página inicial desde una base de datos. Esta misma información es necesaria a lo largo de la experiencia, por lo que pensé que acceder a ella desde esta matriz puede ser más rápido que hacer llamadas a la base de datos todo el tiempo. Al final lo necesito al principio, así que supongo que tiene sentido. Corrígeme si hay una mejor manera. –

+0

Ver a continuación: http://stackoverflow.com/questions/777455/is-there-a-query-language-for-json – Brij

+0

Kenny: ¿Has mirado la solución de @ david !!?!? – billy

Respuesta

45

Puede usar javascript puro

var wanted = items.filter(function(item){return (item.age==18);}); 

Y si su navegador no soporta la versión 1.6 de JavaScript se puede encontrar una implementación del método de filtro en https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter


actualización

Speedwise hay enorme variando (ha habido un error en la prueba) diferencia con respecto a un bucle normal (dependiendo del navegador) .. un vistazo a esta pequeña prueba que hice en http://jsperf.com/array-filter-vs-loop/3

+0

Esto parece bastante simple, me gusta y puedo usarlo también para mucho más. Solo examinando algunas de estas otras sugerencias para ver si algo puede ser mejor en cuanto a rendimiento, supongo que esto se repite un poco, pero tal vez no sea un problema. –

+0

@Kenny Flannery: la "desventaja" es que realiza una llamada a función por artículo. Un bucle 'for' normal es probablemente más rápido. –

+0

Bonito enlace de prueba, usando el bucle for por ahora. –

0

Usar el método de filtro de la matriz , llama a la función de devolución de llamada proporcionada una vez para cada elemento en una matriz.

array.filter(<callbackfucntion>[, <Object to use>]) 
+0

Debe mencionar que este es un método introducido en ES5 y probablemente no esté disponible en todos los navegadores (especialmente en los antiguos). –

+1

¡ahh aprendió algo nuevo! no lo sabía gracias @Felix – CloudyMarble

4

No importa el método que elija (o cualquier items.filter "lenguaje de consulta" para JSON), un bucle for es inevitable.

Si el rendimiento es una preocupación, le recomendaría usar javascript puro en lugar de bibliotecas como jQuery que agregará gastos generales a todo el proceso, como es evidente here.

De este modo, el código se vería así:

var newArray = []; 
for(var i=0;i<items.length;i++) { 
    var item = items[i]; 
    if(item.age == '18') { 
     newArray.push(item); 
    } 
}); 
5

Si usted va a hacer la búsqueda a menudo puede ser mejor para mantener una versión de sus datos en una forma que es rápido de acceso. He usado underscore.js (http://documentcloud.github.com/underscore/) para hacerlo más fácil para mí, pero este código aquí creará un objeto que mantiene sus datos indexados por el campo de edad.

terminas con algo que se parece a esto:

{ 
    "16": [ 
     { 
      "name": "charlie", 
      "age": "16" 
     } 
    ], 
    "18": [ 
     { 
      "name": "ben", 
      "age": "18" 
     }, 
     { 
      "name": "steve", 
      "age": "18" 
     } 
    ] 
} 

El código:

var itemsByAge = _(items).reduce(function(memo, item) { 
    memo[item.age] = memo[item.age] || []; 
    memo[item.age].push(item); 
    return memo; 
}, {}); 

alert(JSON.stringify(itemsByAge["18"])); 
+0

¡¡¡Estupendo !!! ¡Estaba pensando en algo así cuando leía la pregunta! – billy

0

Una vez que tenía ese problema y lo resolví como esto 1- crear una matriz de la matriz 2- cada índice crea un registro de índice por ej.

var pAry=[]; 
var cAry=[{name:'ben', age:'18'}, {name:'steve', age:'18'}] 
pAry[17]=cAry; 

De esta manera cuando u requieren persona con 18 años de edad, obtendrá el índice de 17.

+0

Esto está cerca de lo que decidí, excepto una matriz asociativa u objeto realmente. –

2

haciendo uso de JavaScript magnífica función eval() que evalúa cadena como código en tiempo de ejecución, podemos definir un método prototipo para tipo de matriz

Array.prototype.where = function (query) { 
var newArray = []; 
for(var i=0; i<this.length; i++) { 
    var item = this[i]; 
    if(eval("item" + query)) { 
     newArray.push(item); 
    } 
} 
return newArray; 
}; 

y usarlo con cualquier matriz, que pasa a la consulta como cadena

var newArray= items.where('.age >= 18'); 
Cuestiones relacionadas