2012-02-23 14 views
14

Mam obiekt javascript, a ja chcę rekursywnie wyszukać go, aby znaleźć wszelkie właściwości, które zawierają określoną wartość.Wyszukaj obiekt javascript dla właściwości o określonej wartości?

Javascript, z którym pracuję, został zminimalizowany i nie jest tak łatwy do prześledzenia.

Tło

Używam Bing Maps AJAX SDK. Ma możliwość dodawania dodatkowych warstw kafli. Każdy tilelayer ma obiekt tileworks, który określa format URI dla adresu URL kafli.

Wystąpił problem polegający na tym, że identyfikator URI źródła jest tworzony raz i przechowywany w pamięci podręcznej. Dlatego nie mogę dynamicznie zmieniać parametrów adresu URL (na przykład, aby zmienić kolory nakładki kafelkowej na podstawie pory dnia) dla każdego żądania.

Należy zauważyć, że to zachowanie różni się od interfejsu API Map Google i api Bing Maps dla WP7, które umożliwiają dynamiczne tworzenie adresów URL dla każdego żądania płytki.

Zbuforowany identyfikator URI jest wyszukiwany, a dwa określone parametry są zastępowane, a następnie URI służy do pobrania kafelka.

Ponieważ jest to javascript, chciałbym znaleźć buforowany identyfikator URI i zastąpić go funkcją, która zamiast tego dynamicznie buduje identyfikator URI i zwraca go.

Nie muszę tego robić w każdym środowisku uruchomieniowym, chcę tylko wiedzieć, gdzie jest przechowywana właściwość, więc mogę napisać kod do hax0r.

oryginalne pytanie

Jeżeli ustawić URI do pewnej wartości jak „floobieblaster”, kiedy ustawić punkt przerwania, mogę poszukać obiektu javascript rekurencyjnie dla „floobieblaster” i dostać tę właściwość, że jest przechowywanie że wartość?

Edytuj, aby dodać

Przedmiotem Szukam wydaje się mieć odwołanie cykliczne, więc każdy kod rekurencyjne prawdopodobnie spowoduje stackoverflow.

Czy są jakieś sztuczki edytora/debuggera, z których mógłbym skorzystać?

+0

myślę, że mogę potencjalnie zrzucić się obiekt JSON i szukać w ten sposób. Być może jest lepszy sposób? - Nie. Wygląda na to, że obiekt ma okrągłą strukturę. – Alan

+0

Biblioteka Crockforda (patrz cykl.js) https://github.com/douglascrockford/JSON-js obsługuje kodowanie i dekodowanie okrągłych obiektów w json (+ ścieżka jsonpath). Możesz serializować i wyszukiwać, jak sugerujesz, lub po prostu nieznacznie zmienić kod, aby osiągnąć cel bezpośrednio. – davin

Odpowiedz

20

Coś prostego jak to powinno działać:

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

    } 

} 

Jeśli wykonasz searchObj(testObj, 'testValue'); będzie zalogować następujących do konsoli:

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

Oczywiście, można wymienić console.log o co chcesz, lub dodaj parametr wywołania zwrotnego do funkcji searchObj, aby był bardziej przydatny do ponownego użycia.

EDYCJA: Dodano parametr query, który pozwala określić wartość, którą chcesz wyszukać po wywołaniu funkcji.

+6

+1, ale aby zapobiec wyszukiwaniu obiektów w łańcuchu '[[Prototyp]]', należy dołączyć test 'hasOwnProperty'. Rozważ także testowanie dla 'typeof obj [key] == 'function''. – RobG

2

Oto moje rozwiązanie, pasuje do podanego ciągu/wartości za pomocą testu regex i zwraca dopasowaną tablicę.Nie jest rekurencyjny, ale usunąłeś to ze swojego pytania.

To z mojej odpowiedzi w wątku: Search a JavaScript object

samych zasadach, jak inni sugerują, - poszukiwanie obiektu dla danej wartości, dla każdego, kto w poszukiwaniu tego rozwiązania.

Funkcja:

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

Twój obiekt:

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

Do użycia:

(To będzie wyszukiwać swoją tablicę myObject.elems o nazwie '' dopasowanie 'FC')

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

Wynik - sprawdź swoją konsolę:

[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] 

Jeśli chciał dokładne dopasowanie chcesz po prostu zmienić regex w potrójnym rachunku do podstawowego meczu wartości. , tj.

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

Ta funkcja wyszukuje w obiekcie. Będzie pasować do zapytania wyszukiwawczego z właściwością obiektu dla każdej własności. Jest to przydatne, gdy musisz szukać w wielowymiarowym obiekcie. Po spędzeniu kilku godzin otrzymałem ten kod z Google AngularJS Project.

/* 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

To najwyraźniej obsługuje struktury rekurencyjne, których nie akceptuje zaakceptowana odpowiedź. – Automatico

1

Oto wygodniejsze gotowy do pokonania statycznej metody oparte na podejściu Bryana:

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

dla obiektu

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

spowoduje

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

Edytowałem odpowiedź Bryana Downinga, aby wydrukować hierarca hy do głębokich obiektów:

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

Następnie uruchom 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] 
Powiązane problemy