2016-07-14 241 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']} 
      ] 
     } 
    ] 
} 

我希望这将转化为A +符合Q对象(B或C)+(d或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

我已经改变了一点结构,使它运行。您可以修改unpack_filter循环简单地集成到您的代码:

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

正如前面的回答说,你可以通过在列表中的词典或项目均键使用“在”操作循环。通过这种方式,您可以通过if语句来决定如何响应。 上面的答案将打印最内层的字典的键和值,这可能是你想要的。 这是另一个选项,只有在“过滤器”或“谓词”不是关键字时才会打印字典的值。然后,您可以使用** 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')