簡體   English   中英

具有Dict理解的Tuple到Dict Dict的元組

[英]Tuple of Tuple to Dict of Dict with Dict Comprehension

是否可以像這樣轉換一個元組的元組:

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}

您可以將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)在使用字典理解之前。

使用itertools.groupby

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

我認為,Daniel Mesejo的答案很明確。 該答案基於groupby ,但從功能上講, groupbyreduce一種形式。 因此,出於多樣性考慮,我將在這里提供functools.reduce (也使用defaultdict )解決方案:

>>> 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}})

即使這不是字典理解解決方案,但我希望它可以為希望了解回答該問題所需的計算的人提供更多上下文。

您是否喜歡濫用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將返回一個boolean ,這顯然不是此處的預期目的,因此,為什么我建議列出其他答案。

這是我可能會使用的,因為我覺得它相當可讀...

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}})

我針對我喜歡的其他解決方案(groupby)做了一個粗略的基准測試:

l = (("a","aa",1),("a","bb",2),("a","cc",1),("b","ee",9),("b","gg",2))
from collections import defaultdict
def dd():
    d = defaultdict(dict)
    for a,b,c in l:
        d[a][b]=c


def gb():
    {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])}

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

%timeit dd()
%timeit gb()
%timeit gb2()

683 ns ± 1.33 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
2.11 µs ± 129 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.38 µs ± 29.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

(您會看到itemgetter的附加值與必須執行另一次導入的比較,groupby還希望輸入經過排序,因此對於較大的列表,性能損失甚至會更糟...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM