Solución:
(No está buscando a través de “JSON”, está buscando a través de una matriz; la cadena JSON ya se ha deserializado en un gráfico de objeto, en este caso, una matriz).
Algunas opciones:
Utilice un objeto en lugar de una matriz
Si tienes el control de la generación de esta cosa, ¿no? tengo ser una matriz? Porque si no, hay una forma mucho más sencilla.
Diga que estos son sus datos originales:
[
{"id": "one", "pId": "foo1", "cId": "bar1"},
{"id": "two", "pId": "foo2", "cId": "bar2"},
{"id": "three", "pId": "foo3", "cId": "bar3"}
]
¿Podría hacer lo siguiente en su lugar?
{
"one": {"pId": "foo1", "cId": "bar1"},
"two": {"pId": "foo2", "cId": "bar2"},
"three": {"pId": "foo3", "cId": "bar3"}
}
Entonces, encontrar la entrada relevante por ID es trivial:
id = "one"; // Or whatever
var entry = objJsonResp[id];
… como lo está actualizando:
objJsonResp[id] = /* New value */;
… y eliminándolo:
delete objJsonResp[id];
Esto aprovecha el hecho de que en JavaScript, puede indexar en un objeto usando un nombre de propiedad como una cadena, y esa cadena puede ser un literal o puede provenir de una variable como con id
encima.
Poner en un mapa de ID a índice
(Idea tonta, anterior a lo anterior. Se conserva por razones históricas).
Parece que necesita que esto sea una matriz, en cuyo caso no hay realmente una mejor manera que buscar a través de la matriz a menos que desee poner un mapa en ella, lo que podría hacer si tiene el control de la generación de la matriz. objeto. Por ejemplo, digamos que tiene esto originalmente:
[
{"id": "one", "pId": "foo1", "cId": "bar1"},
{"id": "two", "pId": "foo2", "cId": "bar2"},
{"id": "three", "pId": "foo3", "cId": "bar3"}
]
El código de generación podría proporcionar un mapa de ID a índice:
{
"index": {
"one": 0, "two": 1, "three": 2
},
"data": [
{"id": "one", "pId": "foo1", "cId": "bar1"},
{"id": "two", "pId": "foo2", "cId": "bar2"},
{"id": "three", "pId": "foo3", "cId": "bar3"}
]
}
Luego, obteniendo una entrada para la identificación en la variable id
es trivial:
var index = objJsonResp.index[id];
var obj = objJsonResp.data[index];
Esto aprovecha el hecho de que puede indexar en objetos usando nombres de propiedad.
Por supuesto, si lo hace, debe actualizar el mapa cuando modifique la matriz, lo que podría convertirse en un problema de mantenimiento.
Pero si no tiene el control de la generación del objeto, o si actualizar el mapa de identificadores a índices es demasiado código y / o un problema de mantenimiento, entonces tendrá que hacer una búsqueda de fuerza bruta.
Búsqueda de fuerza bruta (corregida)
Algo OT (aunque tú hizo pregunte si había una mejor manera :-)), pero su código para recorrer una matriz es incorrecto. Detalles aquí, pero no puede usar for..in
para recorrer los índices de la matriz (o más bien, si lo hace, debe esforzarse especialmente para hacerlo); for..in
recorre el propiedades de un objeto, no la índices de una matriz. Su mejor apuesta con una matriz no dispersa (y la suya no es dispersa) es un bucle estándar anticuado:
var k;
for (k = 0; k < someArray.length; ++k) { /* ... */ }
o
var k;
for (k = someArray.length - 1; k >= 0; --k) { /* ... */ }
El que prefieras (este último no siempre es más rápido en todas las implementaciones, lo cual es contrario a la intuición para mí, pero ahí estamos). (Con un escaso matriz, puede usar for..in
pero nuevamente haciendo especial cuidado para evitar escollos; más en el artículo vinculado anteriormente.)
Utilizando for..in
en una matriz parece para trabajar en casos simples porque las matrices tienen propiedades para cada uno de sus índices, y sus únicas otras propiedades predeterminadas (length
y sus métodos) están marcados como no enumerables. Pero se rompe tan pronto como establece (o un marco establece) cualquier otra propiedad en el objeto de matriz (lo cual es perfectamente válido; las matrices son solo objetos con un poco de manejo especial alrededor del length
propiedad).
Me había encontrado con este problema para un modelo complejo con varios objetos anidados. Un buen ejemplo de lo que estaba buscando hacer sería este: digamos que tienes una polaroid de ti mismo. Y esa imagen luego se coloca en el maletero de un automóvil. El coche está dentro de una gran caja. La caja está en la bodega de un gran barco con muchas otras cajas. Tuve que buscar en la bodega, buscar en las cajas, revisar el maletero y luego buscar una foto mía existente.
No pude encontrar ninguna buena solución en línea para usar, y usando .filter()
solo funciona en matrices. La mayoría de las soluciones sugirieron simplemente verificar si model["yourpicture"]
existió. Esto era muy indeseable porque, según el ejemplo, eso solo buscaría en la bodega del barco y necesitaba una manera de sacarlos de más abajo por la madriguera del conejo.
Esta es la solución recursiva que hice. En los comentarios, confirmé a TJ Crowder que se requeriría una versión recursiva. Pensé en compartirlo en caso de que alguien se encontrara con una situación compleja similar.
function ContainsKeyValue( obj, key, value ){
if( obj[key] === value ) return true;
for( all in obj )
{
if( obj[all] != null && obj[all][key] === value ){
return true;
}
if( typeof obj[all] == "object" && obj[all]!= null ){
var found = ContainsKeyValue( obj[all], key, value );
if( found == true ) return true;
}
}
return false;
}
Esto comenzará desde un objeto dado dentro del gráfico y se repetirá hacia abajo en cualquier objeto encontrado. Lo uso así:
var liveData = [];
for( var items in viewmodel.Crates )
{
if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true )
{
liveData.push( viewmodel.Crates[items] );
}
}
Lo que producirá una serie de cajas que contenían mi imagen.
Zapping: puede usar esta biblioteca de JavaScript; DefiantJS. No es necesario reestructurar los datos JSON en objetos para facilitar la búsqueda. En su lugar, puede buscar la estructura JSON con una expresión XPath como esta:
var data = [
{
"id": "one",
"pId": "foo1",
"cId": "bar1"
},
{
"id": "two",
"pId": "foo2",
"cId": "bar2"
},
{
"id": "three",
"pId": "foo3",
"cId": "bar3"
}
],
res = JSON.search( data, '//*[id="one"]' );
console.log( res[0].cId );
// 'bar1'
DefiantJS extiende el objeto global JSON con un nuevo método; “búsqueda” que devuelve una matriz con las coincidencias (matriz vacía si no se encontró ninguna). Puede probarlo usted mismo pegando sus datos JSON y probando diferentes consultas XPath aquí:
http://www.defiantjs.com/#xpath_evaluator
XPath es, como sabe, un lenguaje de consulta estandarizado.