[英]Combine dict comprehension with list comprehension to merge dict pairs
[英]Dict merge in a dict comprehension
在 python 3.5 中,我們可以使用 double-splat 解包合並字典
>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> {**d1, **d2}
{1: 'one', 2: 'two', 3: 'three'}
涼爽的。 不過,它似乎並沒有推廣到動態用例:
>>> ds = [d1, d2]
>>> {**d for d in ds}
SyntaxError: dict unpacking cannot be used in dict comprehension
相反,我們必須做reduce(lambda x,y: {**x, **y}, ds, {})
,這看起來更難看。 為什么在該表達式中似乎沒有任何歧義時,解析器不允許使用“一種明顯的方法”?
這不完全是您問題的答案,但我認為使用ChainMap
是一種慣用而優雅的方式來執行您的建議(在線合並字典):
>>> from collections import ChainMap
>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> ds = [d1, d2]
>>> dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}
雖然它不是一個特別透明的解決方案,因為許多程序員可能並不確切知道ChainMap
是如何工作的。 注意(@AnttiHaapala指出)“首次發現使用”等等,這取決於你的意圖,你可能需要對呼叫reversed
通過你的前dict
s轉換ChainMap
。
>>> d2 = {3: 'three', 2:'LOL'}
>>> dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}
>>> dict(ChainMap(*reversed(ds)))
{1: 'one', 2: 'LOL', 3: 'three'}
對我來說,顯而易見的方法是:
d_out = {}
for d in ds:
d_out.update(d)
這很快並且可能非常高效。 我不知道我可以為 python 開發人員說話,但我不知道你期望的版本更容易閱讀。 例如,由於缺少:
,您的理解對我來說更像是集合理解。 FWIW,我不認為有任何技術原因(例如解析器歧義)他們不能添加這種形式的理解解包。
顯然,這些形式是被提議的,但沒有得到足夠普遍的支持來保證實施它們(還)。
final = {}
for data in [d1, d2]:
final = {**final,**data}
您可以使用itertools.chain
或itertools.chain.from_iterable
:
import itertools
ds = [{'a': 1, 'b': 2}, {'c': 30, 'b': 40}]
merged_d = dict(itertools.chain(*(d.items() for d in ds)))
print(merged_d) # {'a': 1, 'b': 40, 'c': 30}
你可以定義這個函數:
from collections import ChainMap
def mergeDicts(l):
return dict(ChainMap(*reversed(list(l))))
然后你可以像這樣使用它:
>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> ds = [d1, d2]
>>> mergeDicts(ds)
{1: 'one', 2: 'two', 3: 'three'}
基於此解決方案,@ilgia-everilä 也提到過,但使其與 Py2 兼容並仍然避免中間結構。 將它封裝在一個函數中使得它的使用非常易讀。
def merge_dicts(*dicts, **extra):
"""
>>> merge_dicts(dict(a=1, b=1), dict(b=2, c=2), dict(c=3, d=3), d=4, e=4)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 4}
"""
return dict((
(k,v)
for d in dicts
for k,v in d.items()
), **extra)
慣用語,沒有ChainMap
:
>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> {k: v for d in [d1, d2] for k, v in d.items()}
{1: 'one', 2: 'two', 3: 'three'}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.