2012-02-23 29 views
14

私はjavascriptオブジェクトを持っていて、再帰的に にしたいです。 特定の値を含むプロパティを検索するためにそれを検索します。特定の値を持つプロパティのjavascriptオブジェクトを検索しますか?

私が扱っているjavascriptは縮小されており、トレースするのは簡単ではありません。

背景

私はBing MapsのAJAX SDKを使用しています。追加のタイルレイヤーを追加することができます。各タイルレイヤには、タイルURLのURI形式を指定するtilesourceオブジェクトがあります。

タイルソースURIが一度作成され、キャッシュされるという問題が発生しました。したがって、URLのパラメータを動的に変更することはできません(たとえば、時刻に基づいてタイルオーバーレイの色を変更するなど)。

この動作は、GoogleのMap APIとWP7用のBing Maps apiとでは異なります。どちらも、それぞれのタイルリクエストのURLを動的に作成できます。

キャッシュされたURIがルックアップされ、2つの特定のパラメータが置き換えられ、次にURIがタイルをフェッチするために使用されます。

これはjavascriptなので、キャッシュされたURIを見つけて、その代わりに動的にURIを作成して返す関数に置き換えたいと思います。

私はこれを毎回実行する必要はなく、プロパティがキャッシュされている場所を知りたいので、hax0rにコードを書くことができます。

元の質問

私は「floobieblaster」のようないくつかの値にURIを設定した場合、私はブレークポイントを設定するとき、私は「floobieblaster」のために再帰的にjavascriptオブジェクトを検索していることを記憶しているプロパティを取得することができます値?

編集

を追加するために私が探していたオブジェクトは、このように任意の再帰的なコードはおそらくstackoverflowの原因となります、循環参照を持っているように見えます。

私が利用できるエディタ/デバッガの魔法はありますか?

+0

を実行します。おそらくもっと良い方法がありますか? - いいえ。オブジェクトに円形の構造があるように見えます。 – Alan

+0

Crockfordのライブラリ(cycle.jsを参照)https://github.com/douglascrockford/JSON-jsは、循環オブジェクトのjson(+ jsonpath)へのエンコードとデコードをサポートしています。提案したようにシリアライズして検索することも、コードを少し変更して直接目的を達成することもできます。 – davin

答えて

20

このような単純な何かが動作するはずです:

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

    } 

} 

あなたがsearchObj(testObj, 'testValue');を実行する場合は、コンソールに次のことをログに記録します。

明らか
property=test value=testValue 
property=test2a value=testValue 

、あなたは、あなたが好きでconsole.logを置き換えることができますsearchObj関数にコールバックパラメータを追加して、再利用可能にしてください。

編集:queryパラメータを追加しました。このパラメータを使用すると、関数を呼び出すときに検索する値を指定できます。

+6

+1ですが、 '[[Prototype]]'チェーン上のオブジェクトの検索を防ぐために、 'hasOwnProperty'テストを含める必要があります。 'typeof obj [key] == 'function'もテストしてみてください。 – RobG

2

私の解決方法は、指定された文字列/値と正規表現テストを一致させ、一致する配列を返します。再帰的ではありませんが、あなたの質問からこれを削除しました。このソリューションの検索では誰のために、与えられた値のオブジェクトを検索する - 他の人が示唆しているとして、 Search a JavaScript object

同じ原則:

これは次のスレッドで私の答えからです。

機能:

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

があなたのオブジェクト:使用方法については

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

(これは、 'FC' を一致する 'name' のあなたのmyObject.elems配列を検索します)

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

結果 - あなたのコンソールを確認してください。

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

あなたが完全一致を望んでいた場合は、単純に基本値と一致するように三元の文に正規表現を変更したいです。 つまり

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

この機能はオブジェクトで検索されます。検索クエリとオブジェクトのすべてのプロパティが一致します。多次元オブジェクトで検索する必要がある場合に便利です 時間を費やした後、私はこのコードを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

これは明らかに受け入れられた答えにはない再帰構造を扱います。 – Automatico

1

ブライアンのアプローチに基づいて、より便利にすぐに行くの静的メソッドです:

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

オブジェクト

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

について

["test", "test2.test2a"] 
0
になります

私はhierarcを印刷するブライアンダウイングの答えを編集しました深いオブジェクトのためのHY:

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

その後、私は潜在的にJSONに出たオブジェクトをダンプし、そのように検索することができると思い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] 
関連する問題