根据Python中的键/值过滤词典和创建子词典?

时间:2009-07-31 21:22:52

标签: python list dictionary filter

好的,我被困住了,需要一些帮助......

如果我有这样的主词典:

data = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value4", "key2": "value5", "key1": "value6"}, 
{"key1": "value1", "key2": "value8", "key1": "value9"} ]

现在,我需要通过该词典来格式化一些数据,即:

for datadict in data:  
    for key, value in datadict.items():  
    ...filter the data...

现在,我怎么会以某种方式在同一个循环中(如果可能的话......如果没有,请提出替代方案)检查某些键的值,如果这些值与我的预设相匹配,那么我会将整个列表添加到另一个字典中因此,当我根据某些键和值从主词典中走出来时,有效地创建了较小的词典?

所以,假设我想创建一个子字典,其中包含key1值为“value1”的所有列表,对于上面的列表,我会给出类似这样的内容:

subdata = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value1", "key2": "value8", "key1": "value9"} ]

5 个答案:

答案 0 :(得分:9)

这是一个不那么漂亮的方式。结果是一个生成器,但是如果你真的想要一个列表,你可以通过调用list()来包围它。大多数情况下并不重要。

谓词是一个函数,如果列表中的字典要剪切它,则决定每个键/值对。默认值接受全部。如果字典中没有k / v对匹配,则拒绝它。

def filter_data(data, predicate=lambda k, v: True):
    for d in data:
         for k, v in d.items():
               if predicate(k, v):
                    yield d


test_data = [{"key1":"value1", "key2":"value2"}, {"key1":"blabla"}, {"key1":"value1", "eh":"uh"}]
list(filter_data(test_data, lambda k, v: k == "key1" and v == "value1"))
# [{'key2': 'value2', 'key1': 'value1'}, {'key1': 'value1', 'eh': 'uh'}]

答案 1 :(得分:3)

其他评论和答案中已经指出的问题(多个相同的密钥不能出现在dict中等等),这就是我的方法:

def select_sublist(list_of_dicts, **kwargs):
    return [d for d in list_of_dicts 
            if all(d.get(k)==kwargs[k] for k in kwargs)]

subdata = select_sublist(data, key1='value1')

答案 2 :(得分:1)

答案太简单了,所以我想我们错过了一些信息。无论如何:

result = []
for datadict in data:
    for key, value in datadict.items():
        thefiltering()

    if datadict.get('matchkey') == 'matchvalue':
        result.append(datadict)

另外,“主词典”不是字典而是列表。只想清除它。

答案 3 :(得分:0)

受到Skurmedal答案的启发,我将其拆分为一个递归方案,以便与嵌套字典数据库一起使用。在这种情况下,“记录”是主干的子字典。谓词定义了我们追踪的记录 - 那些匹配某些(键,值)对的记录,这些记录可以深层嵌套。

def filter_dict(the_dict, predicate=lambda k, v: True):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and _filter_dict_sub(predicate, v):
            yield k, v

def _filter_dict_sub(predicate, the_dict):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and filter_dict_sub(predicate, v):
            return True
        if predicate(k, v):
            return True
    return False

由于这是一个生成器,您可能需要用dict(filter_dict(the_dict))换行以获取过滤字典。

答案 4 :(得分:0)

这是一个老问题,但由于某种原因,没有单行语法答案:

{ k: v for k, v in <SOURCE_DICTIONARY>.iteritems() if <CONDITION> }

例如:

src_dict = { 1: 'a', 2: 'b', 3: 'c', 4: 'd' }
predicate = lambda k, v: k % 2 == 0
filtered_dict = { k: v for k, v in src_dict.iteritems() if predicate(k, v) }

print "Source dictionary:", src_dict
print "Filtered dictionary:", filtered_dict

将产生以下输出:

Source dictionary: {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
Filtered dictionary: {2: 'b', 4: 'd'}