元组到具有Dict理解的Dict的Dict的元组

问题描述 投票:0回答:5

是否可以像这样转换一个元组的元组:

l = (("a","aa",1),("a","bb",2),("a","cc",1),("b","ee",9),("b","gg",2))

到像这样的字典:

{"a":{"aa":1,"bb":2,"cc":1}  "b": {"ee":9,"gg":2}}

使用这样的字典理解:

r = {? for a,b,c in l}
python python-3.x
5个回答
5
投票

您可以将groupby与字典理解结合使用:

from itertools import groupby
from operator import itemgetter

l = (("a", "aa", 1), ("a", "bb", 2), ("a", "cc", 1), ("b", "ee", 9), ("b", "gg", 2))

first = itemgetter(0)
result = {key: {inner: value for _, inner, value in groups} for key, groups in groupby(l, key=first)}

print(result)

输出

{'b': {'gg': 2, 'ee': 9}, 'a': {'cc': 1, 'bb': 2, 'aa': 1}}

如@ juanpa.arrivillaga所述,如果输入未按每个元组的第一个元素排序,则需要对其进行排序,为此,您可以执行以下操作:l = sorted(l, key=first),然后使用字典理解。


3
投票

使用itertools.groupby

itertools.groupby

0
投票

您是否喜欢滥用from itertools import groupby l = (("a","aa",1),("a","bb",2),("a","cc",1),("b","ee",9),("b","gg",2)) print({x: {z[1]: z[2] for z in y} for x, y in groupby(sorted(l, key=lambda x: x[0]), lambda x: x[0])}) # {'a': {'aa': 1, 'bb': 2, 'cc': 1}, 'b': {'ee': 9, 'gg': 2}} 而非其预期目的?我会在这里诚实地使用其他答案,但这也是这样做的另一种方式。

built-ins

使用from collections import defaultdict d = defaultdict(dict) any(d[x[0]].update({x[1]: x[-1]}) for x in l) print(d) defaultdict(dict, {'a': {'aa': 1, 'bb': 2, 'cc': 1}, 'b': {'ee': 9, 'gg': 2}}) 将返回any,这显然不是此处的预期目的,因此,我建议您列出其他答案。


0
投票

我认为,丹尼尔·梅塞霍(Daniel Mesejo)的答案很明确。该答案基于boolean,但从功能上讲,groupbygroupby的一种形式。因此,出于多样性考虑,我将在此处提供reduce(也使用functools.reduce)的解决方案:

defaultdict

尽管这不是字典理解解决方案,但我希望它能为希望了解回答该问题所需的计算的人提供更多上下文。


0
投票

这是我可能会使用的,因为我觉得它相当可读...

>>> from functools import reduce
>>> from collections import defaultdict
>>> l = (("a","aa",1),("a","bb",2),("a","cc",1),("b","ee",9),("b","gg",2))
>>> def update_and_return(acc, up):
...     acc[up[0]][up[1]] = up[2]
...     return acc
... 
>>> reduce(update_and_return, l, defaultdict(dict))
defaultdict(<type 'dict'>, {'a': {'aa': 1, 'cc': 1, 'bb': 2}, 'b': {'ee': 9, 'gg': 2}})

我针对我喜欢的其他解决方案(groupby)做了一个粗略的基准测试:

l = (("a","aa",1),("a","bb",2),("a","cc",1),("b","ee",9),("b","gg",2))
from collections import defaultdict

d = defaultdict(dict)

for a,b,c in l:
    d[a][b]=c


print(d)

defaultdict(dict, {'a': {'aa': 1, 'bb': 2, 'cc': 1}, 'b': {'ee': 9, 'gg': 2}})

((您看到itemgetter的附加值与必须执行另一次导入,groupby还期望输入经过排序,因此对于较大的列表,性能损失甚至会更糟……)

© www.soinside.com 2019 - 2024. All rights reserved.