2017-01-04 13 views
0

私の問題文は私が検索クエリを持っていると私は階層を維持するクエリに一致する辞書を返す必要があります。辞書を再帰的に検索辞書を返す完全なhirerachy

私は最初に達成することができます。

{"Name":"google search","items":[],"properties":{"id":1,"process":123} 

予想される出力:しかし、私は右のこの出力を得るようなもの

の下、開始から 完全な階層を返したい

{ 
    "items":[ 
    {'Name':'chrome','items': 
    [ 
     {"Name":"google search","items":[],"properties":{"id":1,"process":123}} 
    ] 
    }, 
    ] 

} 

これは私のサンプル入力である:

myinput = { 
    "items":[ 
    {'Name':'firefox','items':[],"properties":{"one":1,"two":2}}, 
    {'Name':'chrome','items':[ 
         {'Name':"stackoverflow","items":[],"properties":{"one":1,"two":2}}, 
         {"Name":"google search","items":[],"properties":{"id":1,"process":123}} 
         ], 
         "properties":{"one":1,"two":2}}, 
    {'Name':'new','items':[],"properties":{"one":1,"two":2}}, 
    {'Name':'new','items':[],"properties":{"one":1,"two":2}}, 
    ] 
} 

これまで私が何を試したか

matched_items = [] 
def resursive_fun(Nodes, searchQuery): 
    for key, value in Nodes.iteritems(): 
     if isinstance(value, list): 
      for item in value: 
       matchValue = match_items(searchQuery, item['properties']) 
       if matchValue: 
        matched_items.append(item) 
       resursive_fun(item, searchQuery) 
    return matched_items 

searchDict = {"id": 1, "process": 123} 
resursive_fun(myinput, searchDict) 

答えて

2

私はあなたではなく(あなたが複数の検索を実行する必要がある場合にはあらゆる種類の問題が発生します)グローバルリストを使用するよりも、任意の成功再帰呼び出しの戻り値からあなたの戻り値を構築する必要があると思います。一致がない場合は、特別な意味を持つもの(Noneなど)を返す必要があります。

def recursive_search(data, query): 
    if match_items(searchQuery, data["properties"]):   # base case 
     return data 

    if "items" in data and isinstance(data["items"], list):  # recursive case 
     for item in data["items"]: 
      x = recursive_search(item, query) 
      if x is not None:     # recursive search was successful! 
       return {"Name": data["Name"], "items": [x]} 

    return None       # if search is not successful, return None 

Noneは何かを返さない関数のデフォルトの戻り値であることからreturn Noneは、省略することができます

はこのような何かを試してみてください。しかし、ここでのように、Noneに何らかの意味があるときは明示する方が良いと思います。

最初の一致結果だけでなく、一致するすべての結果を見つけたい場合は、returnの初期の呼び出しを、どこか一致が見つかった場合に値を返すような微妙な動作に置き換えることをお勧めします。

def recursive_search(data, query): 
    result = {} 

    if if "properties" in data and match_items(searchQuery, data["properties"]): 
     result["properties"] = data["properties"] 

    if "items" in data and isinstance(data["items"], list): 
     for item in data["items"]: 
      result_items = [] 
      x = recursive_search(item, query) 
      if x is not None: 
       result_items.append(x) 
     if result_items:   # recursive search found at least one match 
      result["items"] = result_items 

    if result:  # some part of the search found a match (either here or deeper) 
     if "Name" in data: 
      result["Name"] = data["Name"] 
     return result 
    else: 
     return None 

Noneではなく、失敗した一致で空の辞書を返すこともできます。これを行うには、末尾付近のif result: if "Name" in data:行を単一の行if result and "Name" in data:に変更し、無条件でreturn resultを実行します(これをインデントしてelse: return Noneブロックを取り除きます)。再帰的なケースのif x is not Noneチェックをif xに変更します。

+0

これは正常に動作します。しかし、検索クエリが入力セット内の複数の要素と一致する場合、このアルゴリズムはすべての一致結果を返しません。たとえば、検索辞書が 'searchDict = {" process ":123}'の場合、このプロパティでは、2つのアイテムが同じ値を持ちます。その場合は、それは私の階層を持つ2つの辞書を返す必要があります。 – vr22

+0

複数のマッチを処理する必要がある場合は、論理を短絡しないように変更することができます。その状況で厄介なのは、一致するアイテムのサブアイテムをどのように扱うかを決めることだけです。彼らは常に含まれるべきかどうか? – Blckknght

+0

サブアイテムは必ずしもすべて含まれている必要はありません。あなたはいくつかのマッチのシナリオを処理するために短絡しない方法について少し詳しく説明できますか?私のために非常に役立つだろう。前もって感謝します。 – vr22