2017-01-19 15 views
0

私はネストされたdictを持っています。リストには以下のようなリストとdictがあります。python3で特定の順序でネストされたdictを反復する

m = {'abc': 
     {'bcd': [ 
       {'cde':'100','def':'200','efg':'300'}, 
       {'cde':'3000','def':'500','efg':'4000'} 
       ], 
     'ghi': 
     {'mnc': [ 
        {'xyz':'8827382','mnx':'e838','wyew':'2232'} 
       ] 
     } 
     } 
    } 

私の要件は、MNXキーと一致することであり、値が'e838'であれば、その特定の辞書内の他のキーの値を取得します。上記の例から私はxyzキーの値を必要とするかもしれません。

このため、以下のような再帰的ループ関数を作成しました。これは動作しています。しかし、私の質問は、それを行うためのより良い/簡単な方法があるかどうかです。また、キーmnxですべての値を取得する必要がある場合は、同じコードで何ができるか。ありがとう。

注:XMLをdictにjxmlease libの助けを借りて変換しています。アウト

def iterate_dict(dict1,key1,val1): 
    for key, value in dict1.items(): 
     if key == key1 and value == val1: 
      return dict1 
     if isinstance(value,list): 
      for item1 in value: 
       if isinstance(item1,dict): 
        for k,v in item1.items(): 
         if k == key1 and v == val1: 
          return item1 
     if isinstance(value,dict): 
      for key,var in value.items(): 
       if key == key1 and var == val1: 
        return value 
       else: 
        return iterate_dict(value,key1,val1) 
+1

あなたはどこ 'mnx'知ることが起こるのか鍵はなるだろうか?そうでない場合、XMLを辞書に変換するために使用しているXMLライブラリは、 'mnx'を見つけるのに役立ちます。 – loganasherjones

+1

codereview.stackexchange.comにうってつけです – Prajwal

+0

' mnx''はボトムレベルのディクテーションではありません。つまり、リストやディクテーションが含まれていますか?それともそれは起こらないでしょうか? –

答えて

0
m['abc']['bcd'] + m['abc']['ghi']['mnc'] 

[{'cde': '100', 'def': '200', 'efg': '300'}, 
{'cde': '3000', 'def': '500', 'efg': '4000'}, 
{'mnx': 'e838', 'wyew': '2232', 'xyz': '8827382'}] 

あなたは繰り返すのではなく、生のデータを使用する辞書のリストを構築する必要があります。

1

あなたはの一種dictsのリストに辞書を「フラット化」し、必要に応じて照会できます。

def flatten_dict(d): 
    flattened = [] 
    current = {} 
    for k, v in d.items(): 
     if isinstance(v, dict): 
      flattened.extend(flatten_dict(v)) 
     elif isinstance(v, list): 
      flattened.extend(sum((flatten_dict(v_d) for v_d in v), [])) 
     else: 
      current[k] = v 
    if len(current) > 0: 
     flattened = [current] + flattened 
    return flattened 

def values_in_flattened(flattened, key): 
    return list(filter(None, (d.get(key, None) for d in flattened))) or None 

m = {'abc': {'bcd':[{'cde':'100','def':'200','efg':'300'},{'cde':'3000','def':'500','efg':'4000'}], 'ghi':{'mnc':[{'xyz':'8827382','mnx':'e838','wyew':'2232'}]}}} 
mf = flatten_dict(m) 
efg_vals = values_in_flattened(mf, 'efg') 
print(mf) 
print(efg_vals) 

>>> 
[{'xyz': '8827382', 'mnx': 'e838', 'wyew': '2232'}, {'def': '200', 'efg': '300', 'cde': '100'}, {'def': '500', 'efg': '4000', 'cde': '3000'}] 
['300', '4000'] 
0

このコードでは、再帰的なジェネレータを使用して検索を行いますので、それはのようにすべてのソリューションを得られますそれを見つける。

iterate_dictが希望の(キー、値)ペアを持つdictを見つけると、filter_dictが呼び出され、出力を含む新しいdictが作成されます。この新しい辞書には、希望する(キー、値)のペアを除外し、その辞書に含まれる可能性のあるリストまたは辞書を除外することを除いて、filter_dictに渡される辞書の項目が含まれます。しかし、iterate_dictは、これらのリストまたはディクテーションを再帰的に処理して、それ以上のマッチを探します。 iterate_dictがそれ以上の一致を探すことを望まない場合は、コードを変更してそのようにするのは簡単ではありません。下記を参照してください。

希望のキーを含むディクテーションを検索し、そのキーに関連付けられた値を気にしない場合は、val引数としてNoneを渡すか、そのargを省略するだけです。

データを少し修正しましたので、一致が含まれているdictでさらに一致するものを再帰的に検索することができます。

def filter_dict(d, key): 
    return {k: v for k, v in d.items() 
     if k != key and not isinstance(v, (dict, list))} 

def iterate_dict(d, key, val=None): 
    if key in d and (val is None or d[key] == val): 
     yield filter_dict(d, key) 
    yield from iterate_list(d.values(), key, val) 

def iterate_list(seq, key, val): 
    for v in seq: 
     if isinstance(v, list): 
      yield from iterate_list(v, key, val) 
     elif isinstance(v, dict): 
      yield from iterate_dict(v, key, val) 

# test 

data = { 
    'abc': { 
     'bcd': [ 
      {'cde':'100', 'def':'200', 'efg':'300'}, 
      {'cde':'3000', 'def':'500', 'efg':'4000'}, 
      {'abc': '1', 'mnx': '2', 'ijk': '3', 
       'zzz': {'xyzz':'44', 'mnx':'e838', 'yew':'55'} 
      }, 
     ], 
     'ghi': { 
      'mnc': [ 
       {'xyz':'8827382', 'mnx':'e838', 'wyew':'2232'} 
      ] 
     } 
    } 
} 

for d in iterate_dict(data, 'mnx', 'e838'): 
    print(d) 

出力

{'yew': '55', 'xyzz': '44'} 
{'xyz': '8827382', 'wyew': '2232'} 

は、ここでキー'mnx'を含むすべてのdictsを探し検索です:

for d in iterate_dict(data, 'mnx'): 
    print(d) 

出力

{'ijk': '3', 'abc': '1'} 
{'xyzz': '44', 'yew': '55'} 
{'wyew': '2232', 'xyz': '8827382'} 

あなたはは各試合はそれで発見された後、再帰的にだけにiterate_dictを変更、さらに試合のために検索されるのdictたくない場合:

def iterate_dict(d, key, val=None): 
    if key in d and (val is None or d[key] == val): 
     yield filter_dict(d, key) 
    else: 
     yield from iterate_list(d.values(), key, val) 
+0

私は質問に答えを待つことなくこのコードをとにかく投稿することに決めました。ここに遅れています。私が戻ってくる前にこのコードが必要な場合があります。 :) –

関連する問題