Hay una manera mejor que otros de bucle para buscar datos en JSON? Es para editar y borrar.

for(var k in objJsonResp) {
  if (objJsonResp[k].txtId == id) {
    if (action == 'delete') {
      objJsonResp.splice(k,1);
    } else {
      objJsonResp[k] = newVal;
    }
    break;
  }
}

La que se organizan los datos como la lista de mapas.
Como:

[
  {id:value, pId:value, cId:value,...},
  {id:value, pId:value, cId:value,...},
  ...
]
  • Alguien notó la eliminación de no cambiar la longitud y el artículo de @eliminado posición puede permanecer como indefinido (no la indización se realiza) a menos que sea el último elemento, la disminución de la longitud correcta que elimina el último elemento ? Empalme parece actualización de ellos.
InformationsquelleAutor zapping | 2009-12-22

5 Comentarios

  1. 185

    (Usted no está buscando a través de «JSON», usted está buscando a través de una matriz — la cadena JSON ya ha sido deserializar en un objeto gráfico, en este caso una matriz.)

    Algunas de las opciones:

    Utilizar un Objeto en Lugar de una Matriz

    Si usted está en control de la generación de esta cosa, ¿han a un array? Porque si no, hay una manera mucho más sencilla.

    Decir que este es el original de datos:

    [
        {"id": "one",   "pId": "foo1", "cId": "bar1"},
        {"id": "two",   "pId": "foo2", "cId": "bar2"},
        {"id": "three", "pId": "foo3", "cId": "bar3"}
    ]

    Podría hacer la siguiente vez?

    {
        "one":   {"pId": "foo1", "cId": "bar1"},
        "two":   {"pId": "foo2", "cId": "bar2"},
        "three": {"pId": "foo3", "cId": "bar3"}
    }

    A continuación, encontrar la entrada correspondiente por ID es trivial:

    id = "one"; //Or whatever
    var entry = objJsonResp[id];

    …como es la actualización de la misma:

    objJsonResp[id] = /* New value */;

    …y la eliminación:

    delete objJsonResp[id];

    De esta manera se aprovecha el hecho de que en JavaScript, puede índice en un objeto utilizando un nombre de propiedad como una cadena — y que la cadena puede ser un literal, o puede venir de una variable como con id arriba.

    Poner un ID-a-Mapa de Índice de

    (Idea tonta, es anterior a la de arriba. Mantiene por razones históricas.)

    Parece que usted necesita para ser un array, en el que caso de que realmente no hay una mejor manera de buscar a través de la matriz a menos que usted quiere poner un mapa en ella, lo que podría hacer si usted tiene el control de la generación de los objetos. E. g., dicen que usted tiene esta originalmente:

    [
        {"id": "one",   "pId": "foo1", "cId": "bar1"},
        {"id": "two",   "pId": "foo2", "cId": "bar2"},
        {"id": "three", "pId": "foo3", "cId": "bar3"}
    ]

    La generación de código podría proporcionar un id-a-mapa de í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"}
        ]
    }

    Después de conseguir una entrada para la identificación de la variable id es trivial:

    var index = objJsonResp.index[id];
    var obj = objJsonResp.data[index];

    De esta manera se aprovecha el hecho de que puedes índice en los objetos de uso de la propiedad de los nombres.

    Por supuesto, si usted hace eso, usted tiene que actualizar el mapa cuando se modifica la matriz, lo que podría convertirse en un problema de mantenimiento.

    Pero si no estás en control de la generación de los objetos, o la actualización del mapa de identificadores a los índices es demasiado código y/ora de mantenimiento problema, entonces usted tendrá que hacer una búsqueda por fuerza bruta.

    Búsqueda por Fuerza bruta (corregido)

    Un poco OT (aunque hizo preguntar si había una forma mejor 🙂 ), pero el código para el bucle a través de una matriz es incorrecta. Más detalles aquí, pero no puede usar for..in un bucle a través de la matriz de índices (o más bien, si usted lo hace, usted tiene que tener un especial dolores de hacerlo); for..in bucles a través de la propiedades de un objeto, no la índices de una matriz. Su mejor apuesta con un no-matriz dispersa (y el suyo es no dispersa) es un estándar de la antigua bucle:

    var k;
    for (k = 0; k < someArray.length; ++k) { /* ... */ }

    o

    var k;
    for (k = someArray.length - 1; k >= 0; --k) { /* ... */ }

    Lo que usted prefiera (este último no es siempre más rápido en todas las implementaciones, que es contra-intuitivo para mí, pero no lo estamos). (Con un escasa de la matriz, se puede usar for..in pero de nuevo a tomar especiales precauciones para evitar trampas; más información en el artículo enlazado más arriba.)

    Utilizando for..in en una matriz parece para trabajar en casos simples, ya que las matrices tienen propiedades para cada uno de sus índices, y su única otra de las propiedades predeterminadas (length y sus métodos) se marcan como no enumerable. Pero se rompe tan pronto como se establece (o un marco de conjuntos) otras propiedades en el objeto de matriz (que es perfectamente válido; las matrices son sólo los objetos con un poco de manejo especial alrededor de la length de la propiedad).

    • Thx, voy a tomar el primer camino parece mejor.
    • Gran hack: for(var i=someArray.longitud;0<–i;){/* … */}
    • Esto no funciona para un verdadero objeto gráfico. Usted sólo cubre una capa (la parte superior). Si este modelo fuera más complejo que una anidados valor, no se encuentran.
    • Muy cierto. El OP de datos no anidados. Si los datos anidados, es bastante fácil hacer una versión recursiva de la anterior. 🙂
    • Yo había pensado en una versión recursiva sería necesario y acababa de hacer uno. Me sugirió que la solución dada fue sólo la capa superior para ver lo que sus pensamientos estaban. En caso de que alguien más estaba interesado en el uso de la versión recursiva he publicado a continuación.
  2. 8

    Me había encontrado con este problema para un modelo complejo con varios objetos anidados. Un buen ejemplo de lo que yo estaba buscando en hacer sería esto: digamos que usted tiene una polaroid de sí mismo. Y que la imagen se coloca luego en un maletero de un coche. El coche está en el interior de una caja grande. La caja es en la bodega de un barco grande con muchas otras cajas. Tuve que buscar en la bodega, busque en los cajones, compruebe el tronco, y, a continuación, busque una imagen existente de mí.

    No podía encontrar una buena solución en línea para el uso, y el uso de .filter() sólo funciona en las matrices. La mayoría de las soluciones sugeridas sólo la comprobación para ver si model["yourpicture"] existido. Esto fue muy indeseable porque, desde el ejemplo, que sólo la búsqueda de la bodega de la nave, y yo necesitaba una manera de llegar a ellos desde más abajo el agujero del conejo.

    Esta es la solución recursiva he hecho. En los comentarios, me confirmó de T. J. Crowder que una versión recursiva sería necesario. Pensé que iba a compartir en caso de que alguien vino a través de un complejo similar situación.

    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;
    }

    Este comenzará a partir de un determinado objeto dentro de la gráfica, y recurse hacia abajo de los objetos encontrados. Yo lo uso como esto:

    var liveData = [];
    for( var items in viewmodel.Crates )
    {
        if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true )
        {
            liveData.push( viewmodel.Crates[items] );
        }
    }

    Que va a producir una gama de las Cajas que contenía mi imagen.

  3. 6

    Zapping – puede utilizar esta javascript lib; DefiantJS. No hay necesidad de reestructurar los datos JSON en objetos para facilitar la búsqueda. En su lugar, usted puede buscar en la estructura JSON con una expresión XPath como este:

        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 se extiende el objeto global JSON con un nuevo método de «búsqueda» que devuelve la matriz de los partidos (matriz vacía si no se había encontrado ninguno). Puedes probarlo por ti mismo por pegar tus datos en JSON y prueba diferentes consultas XPath aquí:

    http://www.defiantjs.com/#xpath_evaluator

    XPath es, como usted sabe, un estandarizados de lenguaje de consulta.

    • Gracias, le recuerda a probarlo la próxima vez.
  4. 0

    Si los datos JSON en su matriz se ordenan de alguna manera, hay una variedad de la búsqueda se pueden implementar. Sin embargo, si usted no está tratando con una gran cantidad de datos, entonces usted está probablemente va a estar bien con una operación O(n) aquí (como ustedes). Otra cosa sería probablemente una exageración.

  5. 0

    Si usted está haciendo esto en más de un lugar en su aplicación tendría sentido usar un cliente-lado JSON de la base de datos debido a la creación personalizada de funciones de búsqueda es desordenado y menos sostenible que la alternativa.

    Retirar ForerunnerDB la cual proporciona una muy potente, del lado del cliente JSON sistema de base de datos e incluye una muy simple lenguaje de consulta para ayudar a hacer exactamente lo que usted está buscando:

    //Create a new instance of ForerunnerDB and then ask for a database
    var fdb = new ForerunnerDB(),
        db = fdb.db('myTestDatabase'),
        coll;
    
    //Create our new collection (like a MySQL table) and change the default
    //primary key from "_id" to "id"
    coll = db.collection('myCollection', {primaryKey: 'id'});
    
    //Insert our records into the collection
    coll.insert([
        {"name":"my Name","id":12,"type":"car owner"},
        {"name":"my Name2","id":13,"type":"car owner2"},
        {"name":"my Name4","id":14,"type":"car owner3"},
        {"name":"my Name4","id":15,"type":"car owner5"}
    ]);
    
    //Search the collection for the string "my nam" as a case insensitive
    //regular expression - this search will match all records because every
    //name field has the text "my Nam" in it
    var searchResultArray = coll.find({
        name: /my nam/i
    });
    
    console.log(searchResultArray);
    
    /* Outputs
    [
        {"name":"my Name","id":12,"type":"car owner"},
        {"name":"my Name2","id":13,"type":"car owner2"},
        {"name":"my Name4","id":14,"type":"car owner3"},
        {"name":"my Name4","id":15,"type":"car owner5"}
    ]
    */

    Descargo de responsabilidad: yo soy el desarrollador de ForerunnerDB.

Dejar respuesta

Please enter your comment!
Please enter your name here