2012-02-23 21 views
14

Tengo un objeto javascript, y quiero recursivamente búsqueda para encontrar las propiedades que contienen un valor específico.¿Busca un objeto javascript para una propiedad con un valor específico?

El javascript con el que estoy trabajando se ha modificado y no es fácil de seguir.

Antecedentes

estoy usando el SDK de Bing Maps AJAX. Tiene la capacidad de agregar capas de mosaico adicionales. Cada capa de mosaico tiene un objeto de fuente de mosaico, que especifica el formato de URI para la URL de mosaico.

Me encontré con un problema donde el URI de origen de azulejos se crea una vez y se almacena en caché. Por lo tanto, no puedo cambiar dinámicamente los parámetros de la URL (por ejemplo, para cambiar los colores de la superposición de mosaicos en función de la hora del día) para cada solicitud.

Tenga en cuenta que este comportamiento es diferente que la API de Google Maps y la API de Bing para WP7, que le permiten crear dinámicamente la URL para cada solicitud de mosaico.

Se busca el URI en caché y se reemplazan dos parámetros específicos, luego se utiliza el URI para recuperar el mosaico.

Dado que se trata de javascript, me gustaría encontrar el URI en caché y reemplazarlo con una función que, en lugar de ello, crea dinámicamente el URI y lo devuelve.

No necesito hacer esto cada tiempo de ejecución, solo deseo y la idea de dónde se está almacenando la propiedad en la memoria caché, por lo que puedo escribir código para hax0r.

pregunta original

Si fijo el URI a algún valor como "floobieblaster", cuando me puse un punto de interrupción, se puede buscar el objeto JavaScript de forma recursiva para "floobieblaster" y obtener la propiedad que está almacenando que ¿valor?

Editar para añadir

El objeto que estoy buscando parece tener una referencia circular, por lo que cualquier código recursivo probablemente causará un stackoverflow.

¿Hay algún truco de editor/depurador que pueda utilizar?

+0

Creo que potencialmente pueda volcar el objeto a JSON y la búsqueda de esa manera. Tal vez hay una mejor manera? - No. Parece que el objeto tiene una estructura circular. – Alan

+0

La biblioteca de Crockford (ver ciclo.js) https://github.com/douglascrockford/JSON-js admite la codificación y decodificación de objetos circulares en json (+ jsonpath). Puede serializar y buscar como sugirió, o simplemente cambiar el código ligeramente para lograr su objetivo directamente. – davin

Respuesta

20

Algo tan simple como esto debería funcionar:

var testObj = { 
    test: 'testValue', 
    test1: 'testValue1', 
    test2: { 
     test2a: 'testValue', 
     test2b: 'testValue1' 
    } 
} 

function searchObj (obj, query) { 

    for (var key in obj) { 
     var value = obj[key]; 

     if (typeof value === 'object') { 
      searchObj(value, query); 
     } 

     if (value === query) { 
      console.log('property=' + key + ' value=' + value); 
     } 

    } 

} 

Si ejecuta searchObj(testObj, 'testValue'); se registrará el siguiente en la consola:

property=test value=testValue 
property=test2a value=testValue 

Obviamente, se puede reemplazar el console.log con lo que quieras, o agregue un parámetro de devolución de llamada a la función searchObj para que sea más reutilizable.

EDIT: Agregó el parámetro query que le permite especificar el valor que desea buscar cuando llama a la función.

+6

+1 pero para evitar la búsqueda de objetos en la cadena '[[Prototype]]', se debe incluir una prueba 'hasOwnProperty'. Considere la posibilidad de probar 'typeof obj [key] == 'function'' también. – RobG

2

Aquí está mi solución, coincide con la cadena/valor dado con una prueba de expresiones regulares y devuelve la matriz coincidente.No es recursivo, sin embargo, ha eliminado esto de su pregunta.

Esto es de mi respuesta en el siguiente hilo: Search a JavaScript object

mismos principios, como otros han sugerido - buscar un objeto para el valor dado, para cualquier persona en busca de esta solución.

La función:

Array.prototype.findValue = function(name, value){ 
    var array = $.map(this, function(v,i){ 
     var haystack = v[name]; 
     var needle = new RegExp(value); 
     // check for string in haystack 
     // return the matched item if true, or null otherwise 
     return needle.test(haystack) ? v : null; 
    }); 
    return this; 
} 

Su objeto:

myObject = { 
     name : "soccer", 
     elems : [ 
      {name : "FC Barcelona"}, 
      {name : "Liverpool FC"} 
     ] 
    }, 
    { 
     name : "basketball", 
     elems : [ 
      {name : "Dallas Mavericks"} 
     ] 
    } 

Para el uso:

(Esto buscará la matriz myObject.elems para un 'nombre' juego 'FC')

var matched = myObject.elems.findValue('name', 'FC'); 
console.log(matched); 

El resultado - comprobar su consola:

[Object, Object, keepMatching: function, findValue: function] 
0: Object 
name: "FC Barcelona" 
__proto__: Object 
1: Object 
name: "Liverpool FC" 
__proto__: Object 
length: 2 
__proto__: Array[0] 

Si desea una coincidencia exacta que le basta con cambiar la expresión regular en la declaración ternaria a un partido básica de valor. decir

v[name] === value ? v : null 
2

Esta función Buscar en objeto. Relacionará la consulta de búsqueda con las propiedades de cada objeto. Esto es útil cuando necesite buscar objetos multidimensionales. Después de pasar horas, obtuve este código del Proyecto AngularJS de Google.

/* Seach in Object */ 

var comparator = function(obj, text) { 
if (obj && text && typeof obj === 'object' && typeof text === 'object') { 
    for (var objKey in obj) { 
     if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) && 
       comparator(obj[objKey], text[objKey])) { 
      return true; 
     } 
    } 
    return false; 
} 
text = ('' + text).toLowerCase(); 
return ('' + obj).toLowerCase().indexOf(text) > -1; 
}; 

var search = function(obj, text) { 
if (typeof text == 'string' && text.charAt(0) === '!') { 
    return !search(obj, text.substr(1)); 
} 
switch (typeof obj) { 
    case "boolean": 
    case "number": 
    case "string": 
     return comparator(obj, text); 
    case "object": 
     switch (typeof text) { 
      case "object": 
       return comparator(obj, text); 
      default: 
       for (var objKey in obj) { 
        if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { 
         return true; 
        } 
       } 
       break; 
     } 
     return false; 
    case "array": 
     for (var i = 0; i < obj.length; i++) { 
      if (search(obj[i], text)) { 
       return true; 
      } 
     } 
     return false; 
    default: 
     return false; 
} 
}; 
+1

Esto aparentemente maneja estructuras recursivas, lo que no sucede con la respuesta aceptada. – Automatico

1

Aquí es una forma más cómoda listos para ir método estático basado en el enfoque de Bryan:

/** 
* Find properties matching the value down the object tree-structure. 
* Ignores prototype structure and escapes endless cyclic nesting of 
* objects in one another. 
* 
* @param {Object} object Object possibly containing the value. 
* @param {String} value Value to search for. 
* @returns {Array<String>} Property paths where the value is found. 
*/ 
getPropertyByValue: function (object, value) { 
    var valuePaths; 
    var visitedObjects = []; 

    function collectValuePaths(object, value, path, matchings) { 

    for (var property in object) { 

     if (
     visitedObjects.indexOf(object) < 0 && 
     typeof object[property] === 'object') { 

     // Down one level: 

     visitedObjects.push(
      object); 

     path = 
      path + 
      property + "."; 

     collectValuePaths(
      object[property], 
      value, 
      path, 
      matchings); 
     } 

     if (object[property] === value) { 

     // Matching found: 

     matchings.push(
      path + 
      property); 
     } 

     path = ""; 
    } 

    return matchings; 
    } 

    valuePaths = 
    collectValuePaths(
     object, 
     value, 
     "", 
     []); 

    return valuePaths; 
} 

Para que un objeto

var testObj = { 
    test: 'testValue', 
    test1: 'testValue1', 
    test2: { 
     test2a: 'testValue', 
     test2b: 'testValue1' 
    } 
} 

dará lugar a

["test", "test2.test2a"] 
0

Edité la respuesta de Bryan Downing para imprimir una jerarquía HY para objetos profundos:

function searchObj (obj, query, prefix /*not to be set*/) { 
    prefix = prefix || "---"; 
    var printKey; 

    for (var key in obj) { 
     var value = obj[key]; 

     if (typeof value === 'object') { 
      if (searchObj(value, query, prefix + "|---")) { 
       console.log(prefix + ' ' + key); 
       printKey = true; 
      } 
     } 

     if (value === query) { 
      console.log(prefix + ' ' + key + ' = ' + value); 

      return true; 
     } 
    } 

    return printKey; 
} 

A continuación, ejecute searchObj(testObj, 'testValue');

0
//example from the Binance API. 
//They return a ticker object with ALL of their currency pairs 
//that contain the current price of each pair. 
//We want to allow users to enter in a currency pair, 
//and return the current ask price of the currency. E.g., 
//users are asking for something that we do not know if it 
// exists until the ticker object is returned. Therefore, we 
//must search for a property in the object, if it exists, 
//return the value of the found property. 

let symbol = 'LTCBTC'; 
if (symbol in ticker) { 
    console.log(ticker[symbol]); 
} else { 
console.log('symbol not found or not supported'); 
} 
//This example uses the javascript property accessor to access 
//the property once we've verified it is in the 
//object [js property accessors][1] and the in 
//operator [js in property][2] 
Cuestiones relacionadas