2016-10-26 109 views
1

我有一个不一定具有相同键的字典列表。我正在尝试创建每个包含特定键的字典中包含的值的新列表。Python从具有特定键的每个字典的字典列表创建列表

E.g.

dict1 = {'key1': 1, 'key2': 2, 'key4': 4} 
dict2 = {'key2': 2, 'key3': 3} 
dict3 = {'key1': 1, 'key2': 2, 'key3': 3} 

dict_list = [dict1, dict2, dict3] 

现在,我试图从dict_list创建列表如下:

key2vals = [dict['key2'] for dict in dict_list] 
print(key2vals) 
    [2, 2, 2] 

行之有效,因为“KEY2”被包含在列表中的每个词典。但是,当我尝试一个没有出现在每本字典中的密钥时,我会遇到一个错误。例如。 'key1':

>>> key1vals = [dict['key1'] for dict in dict_list] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <listcomp> 
KeyError: 'key1' 

有没有一个简短而直接的方法,我可以做下面的事情,这是行不通的?

# This does not work 
key1vals = [dict['key1'] if 'key1' in dict for dict in dict_list] 

什么是最Python化的方法来实现这一目标?

答: 的并if语句应该已经本末倒置:

key1vals = [dict['key1'] for dict in dict_list if 'key1' in dict ] 

而且,与AbrahamB和DJV的建议,我能够将默认值添加到这些字典没有搜索关键字:

[dict.get('key1', 0) for dict in dict_list] 

回答

2
dict1 = {'key1': 1, 'key2': 2, 'key4': 4} 
dict2 = {'key2': 2, 'key3': 3} 
dict3 = {'key1': 1, 'key2': 2, 'key3': 3} 

dict_list = [dict1, dict2, dict3] 

keys = ['key1', 'key2', 'key3', 'key4', 'key5'] 
for key in keys: 
    values = [d[key] for d in dict_list if key in d] 
    print(values) 
[1, 1] 
[2, 2, 2] 
[3, 3] 
[4] 
[] 

但是相同的项目查找在这里完成了两次:key in dd[key]。你能避免它:

values = list(filter(None, (d.get(key) for d in dict_list))) 

values = [i for i in (d.get(key) for d in dict_list) if i is not None] 

新增: 正如你在评论中提到,你实际上需要0如果key不是在字典。只要使用get方法用默认值:

values = [d.get(key, 0) for d in dict_list] 
[1, 0, 1] 
[2, 2, 2] 
[0, 3, 3] 
[4, 0, 0] 
[0, 0, 0] 
2

绝对如此。该字典有一个“get”方法,您可以使用它。

例如

a = {} 
a.get('this-does-not-exist') 

这将返回一个无类型。现在

你可以更大胆的尝试,比如如果没有找到返回的默认值:

a = {} 
a.get('this-does-not-exist', []) 

它会返回一个空列表[]。

+0

您可以在原始示例问题中使用a.get('key','defaultValue')格式吗?我并不完全遵循如何在更大的图景中使用它。 –

+0

DJV刚刚在另一条评论中提供了答案:[d.get('key1',0)for dict_list] –

1

你是八九不离十:

key1vals = [d['key1'] for d in dict_list if 'key1' in d] 

要获得所有键的值:

all_keys = {key for d in dict_list for key in d} 

result_dict = {} 
for key in all_keys: 
    result_dict[key] = [d[key] for d in dict_list if key in d] 

print(result_dict) 

它打印:

{'key1': [1, 1], 'key4': [4], 'key3': [3, 3], 'key2': [2, 2, 2]} 
0

感谢您的建议!我发现了另一个解决方案,根本扭转了“”和“如果”在我以前尝试声明:

>>> key1vals = [dict['key1'] for dict in dict_list if 'key1' in dict] 
>>> key1vals 
[1, 1] 
>>> 

请问过滤器或“获取”的方法首选呢?

+0

我会建议使用get,因为它更干净。您已经在dict ['key1']中调用密钥,所以这会比dict.get('key1') – AbrahamB

+0

更短。是的,它更短,但我认为d'语言中的if'key1'可能会更加恶心,更易于阅读。这种方法从字面上检查字典是否有“key1”键。你不能以任何方式出错。 – blacksite

+0

我可以在dict_list中添加一个“else”语句,如>>> key1vals = [dict ['key1'] for dict in if key1'dict else 0]。然后我想要key1vals包含[1,0,1]。 –