簡體   English   中英

自指字典理解

[英]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.

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