在Python中如何根据键/值过滤字典并创建子字典?

5 投票
5 回答
8766 浏览
提问于 2025-04-15 13:19

好的,我遇到麻烦了,需要一些帮助...

假设我有一个主字典,长这样:

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 个回答

2

针对其他评论和回答中提到的问题(比如字典里不能有多个相同的键等等),我会这样做:

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')
3

这是一个老问题,但不知为什么没有简单的一行代码来回答:

{ 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'}
9

这里有一种不是特别好看的做法。结果是一个生成器,但如果你真的想要一个列表,可以用 list() 把它包起来。其实大多数情况下,这个区别并不重要。

这个“谓词”是一个函数,它用来判断列表中的每一个字典的键值对是否符合条件。默认情况下,它会接受所有的字典。如果字典中的任何一个键值对不符合条件,那么这个字典就会被拒绝。

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'}]

撰写回答