2016-07-14 5 views
1

私はかなりPythonの新人です。そして、私はn深度の辞書を使って最終結果としてフィルタクエリを構築しようとしています。その中には他の辞書やリストがあります。Pythonでリストやその他の辞書を含む深くネストされた辞書をトラバースするにはどうしたらいいですか?

これは私の構造です:!

filters = { 
    predicate: 'AND', 
    filters: [ 
     {'property_class_id': 10, operator: 'contains', operands: ['FOO']}, 
     { 
      predicate: 'NOT', 
      filters: [{ 
       predicate: 'OR', 
       filters: [ 
        {'property_class_id': 1, operator: 'contains', operands: ['Hello']}, 
        {'property_class_id': 2, operator: 'contains', operands: ['my search term']} 
       ] 
      }] 
     }, 
     { 
      predicate: 'OR', 
      filters: [ 
       {'property_class_id': 3, operator: 'contains', operands: ['my search term']}, 
       {'property_class_id': 4, operator: 'contains', operands: ['my search term']} 
      ] 
     } 
    ] 
} 

私は、これはQオブジェクトとA +(B OR C)+(D OR E)に変換するだろう期待しています。

しかし、私の最初の問題は、どのように各キー値のペアを通過するこの辞書を横断するのですか?

これはこれまでのものですが、forループは辞書のみを受け入れるため、リストにヒットしたら制限を見ることができます。

def unpack_filter(self, filters): 
    q_object = Q() 
    q_list = [] 

    for key, value in filters.iteritems(): 
     if isinstance(value, list) or isinstance(value, dict): 
      self.unpack_filter(value) 
     else: 
      print "{0} : {1}".format(key, value) 

答えて

0

構造を少し変更して動作させました。あなたは、リスト内の辞書やアイテムのいずれかでキーをループに「の」演算子を使用することができます前の回答で述べたように

base_filter = { 
    'predicate': 'AND', 
    'filters': [ 
    {'property_class_id': 10, 'operator': 'contains', 'operands': ['FOO']}, 
    { 
     'predicate': 'NOT', 
     'filters': [{ 
     'predicate': 'OR', 
     'filters': [ 
      {'property_class_id': 1, 'operator': 'contains', 'operands': ['Hello']}, 
      {'property_class_id': 2, 'operator': 'contains', 'operands': ['my search term']} 
     ] 
     }] 
    }, 
    { 
     'predicate': 'OR', 
     'filters': [ 
     {'property_class_id': 3, 'operator': 'contains', 'operands': ['my search term']}, 
     {'property_class_id': 4, 'operator': 'contains', 'operands': ['my search term']} 
     ] 
    } 
    ] 
} 

# try to avoid using/overwriting the 'filter' name as it's a built-in function 
# https://docs.python.org/2/library/functions.html#filter 
# this is why I'm using names such as 'curr_filter' and 'f' 

def unpack_filter(curr_filter): 
    # ... do something with curr_filter['predicate'] ... 
    for f in curr_filter['filters']: 
    if 'filters' in f: 
     unpack_filter(f)  
    else: 
     for key, value in f.iteritems(): 
     print '{0} : {1}'.format(key, value) 

unpack_filter(base_filter) 
0

:あなたは、単にあなたのコードに変更しunpack_filterループを統合することができます。こうすることで、応答する方法を決定するif文で1つのループを持つことができます。 上記の答えはあなたが望むかもしれない最も内側の辞書のキーと値を表示します。 'filters'または 'predicates'がキーでない場合にのみ、ディクショナリの値を出力する別のオプションがあります。 ** kwargsを使用して、正しく構造化されている場合は、最も内側の辞書を直接Q()オブジェクトに渡して、クエリのキーワード引数を作成できます。ここで

def unpack_filter(curr_filter): 
    for f in curr_filter: 
    if f == 'filters': 
     unpack_filter(curr_filter[f]) 
    elif f == 'predicate': 
     print curr_filter[f] 
    elif 'filters' in f or 'predicate' in f: 
     unpack_filter(f) 
    else: 
     print f 

はキーワード引数として辞書を渡す簡単な例です:

filters = {'name__icontains': 'Google'} 
def f(**kwargs): 
    val = kwargs.pop('name__icontains') 
    print val 

# the next two function calls print the same thing 
f(**filters) 
f(name__icontains='Google')