[英]Self-referential dictionary comprehension
最近,我在回答一個問題。 代碼按預期工作。 但我想看看我是否可以實現我很少使用的字典理解。 首先,讓我解釋一下這個問題。
OP 有一個示例列表,例如M1 = [['a', 14], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
。 他們想要一個與此類似的 output。 [['a',14,7,16],['b',3,15],['c',22,1,5]]
。 有道理,所以我創建了一個答案。
原始代碼
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
for lsts in x:
if lsts[0] in dictX.keys():dictX[lsts[0]].extend(lsts[1:])
else:dictX[lsts[0]] = lsts[1:]
output
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
我的 go 在這個
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x}
錯誤
Traceback(最近一次調用最后):文件“/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py”,第 3 行,在 dictX ={(dictX[lsts[0]]].extend(lsts[ 1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x} File "/Users/aspera/Documents/Python/Py_Programs/data/ timeComplexity/test.py",第 3 行,在 dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]] ): lsts[1:] for lsts in x} KeyError: 'a'
我對此的看法在很多方面似乎都是錯誤的。 我將此用作參考(已接受答案的最高評論)
{(a if condition else b): value for key, value in dict.items()}
有什么辦法可以把它變成聽寫理解。 我想要一個示例,它與我提供的參考和我在原始代碼中使用的邏輯一致
由於嵌套循環,速度一點也不快,但它是可行的。 在 dict 理解中使用列表理解。
seq = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
res = {i[0]:[k for j in seq if j[0] == i[0] for k in j[1:]] for i in seq}
print(res)
Output
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
PS:我意識到這個問題與在Python 中進行列表/字典理解時是否可以訪問當前 object 更相關? ,如果有人認為這是一個騙子,請務必將其標記為這樣,我不確定,所以我將其保留。
通常,您將無法在推導中引用字典本身,因為在推導完成之前,名稱不會分配給結果字典,因此您必須滿足於預定義字典*並利用 mutating現有字典的方法。
由於您正在遍歷輸入列表,因此無論何時遇到該鍵,您都需要使用新值更新現有字典。 由於您不能在字典理解中使用賦值,因此您需要使用dict.update()
方法(或__setitem__
或setdefault
)。 該方法始終返回None
,因此您可以利用它在字典理解中的許多不同位置實現所需的副作用。
特別是,將執行任何過濾條件子句,因此您可以使用它。 或者, expr or value
將評估表達式,該表達式將始終返回None
,並且由於這是錯誤的,整個表達式的計算結果為value
,因此您可以將該表達式放在鍵或值中。 這給了我們以下可能性:
過濾子句中的副作用:
d = {}
d = {k: d[k] for k, *vals in x if d.update({k: d.get(k, []) + vals}) is None}
在expr or key
表達式中具有副作用:
d = {}
d = {d.update({k: d.get(k, []) + vals}) or k: d[k] for k, *vals in x}
在expr or value
表達式中具有副作用:
d = {}
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for k, *vals in x}
* 使用賦值表達式(Python 3.8+),你可以用這種可憎的方式在理解本身內預定義字典:
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for i, (k, *vals) in enumerate(x) if i or not (d := {})}
這使用enumerate()
來檢測您何時進行第一次迭代,在這種情況下,賦值表達式可以構造在理解的 rest 中使用的字典。 在第一次迭代之后,賦值表達式不再被計算,因此d
在計算過程中不會被重新賦值。
注意:顯然,此答案中顯示的所有方法都很糟糕。 理解中的副作用是不必要的、出乎意料的、令人困惑的,總而言之,是愚蠢的。 不要使用此代碼。 但看到什么是可能的很有趣!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.