我有一个字典列表和一个可以从列表中的每个字典中提取值的函数。目标是我得到一个字典,其中键是给定函数返回的值,当我从给定的字典列表中传递字典时。返回字典中的相应值应该是原始字典列表中的字典子集,给定函数返回相应的键。
我知道这个解释非常令人困惑,所以我在一个实现中展示它:
keygen = lambda x: x['key']
data = [{'key': 'key1',
'data': 'value2'},
{'key': 'key3',
'data': 'value2'},
{'key': 'key2',
'data': 'value2'},
{'key': 'key2',
'data': 'value2'},
{'key': 'key1',
'data': 'value2'}]
def merge_by_keygen(data, keygen):
return_value = {}
for dataset in data:
if keygen(dataset) not in return_value.keys():
return_value[keygen(dataset)] = []
return_value[keygen(dataset)].append(dataset)
return return_value
merge_by_keygen(data, keygen)
返回:
{'key3': [{'data': 'value2', 'key': 'key3'}],
'key2': [{'data': 'value2', 'key': 'key2'}, {'data': 'value2', 'key': 'key2'}],
'key1': [{'data': 'value2', 'key': 'key1'}, {'data': 'value2', 'key': 'key1'}]}
我正在寻找相同逻辑的更好,更紧凑的实现,比如一些字典/列表推导。谢谢!
答案 0 :(得分:5)
<强>实施强>
from itertools import groupby
from operator import itemgetter
groups = groupby(sorted(data, key = itemgetter('key')), key = itemgetter('key'))
data_dict = {k : list(g) for k, g in groups}
或者如果您更喜欢单行
data_dict = {k : list(g)
for k, g in groupby(sorted(data,
key = itemgetter('key')),
key = itemgetter('key'))}
<强>输出强>
{'key1': [{'data': 'value2', 'key': 'key1'},
{'data': 'value2', 'key': 'key1'}],
'key2': [{'data': 'value2', 'key': 'key2'},
{'data': 'value2', 'key': 'key2'}],
'key3': [{'data': 'value2', 'key': 'key3'}]}
答案 1 :(得分:2)
如果您不介意使用第三方软件包,可以使用toolz.groupby轻松完成:
>>> import toolz
>>> toolz.groupby(keygen, data)
{'key1': [{'data': 'value2', 'key': 'key1'},
{'data': 'value2', 'key': 'key1'}],
'key2': [{'data': 'value2', 'key': 'key2'},
{'data': 'value2', 'key': 'key2'}],
'key3': [{'data': 'value2', 'key': 'key3'}]}
使用toolz.groupby('key', data)
答案 2 :(得分:1)
我不认为这是理解的,但你可以使用collections.defaultdict(list)
实例使它更整洁:
import collections
def merge_by_keygen(data, keygen):
return_value = collections.defaultdict(list)
for dataset in data:
key = keygen(dataset)
return_value[key].append(dataset)
return return_value
对我来说这看起来很干净 - 如果你愿意的话,你可以在你调用keygen
功能的地方移动,但我认为你可能会失去清晰度。
答案 3 :(得分:0)
我认为这样做
return_value = {}
for d in data:
return_value.setdefault(keygen(d), []).append(d)
你可以用列表理解来编写它,但是使用列表推导的副作用来影响数据,然后建立一个无结果列表然后扔掉它是很难看的......
r = {}
[r.setdefault(keygen(d), []).append(d) for d in data]
你的函数的核心都归结为dictionary setdefault方法。关于调用keygen的所有三行,检查键是否在返回字典中,如果它不创建空列表,将空列表存储在字典中,然后再次查询字典以使列表准备好附加到它 - 全部由setdefault()完成。