[英]Recursive list comprehension in Python?
是否可以在 Python 中定義遞歸列表理解?
可能是一個簡單的例子,但大致如下:
nums = [1, 1, 2, 2, 3, 3, 4, 4]
willThisWork = [x for x in nums if x not in self] # self being the current comprehension
這樣的事情有可能嗎?
不,沒有(有記錄的、可靠的、穩定的,...;-) 方式來指代“當前的理解”。 你可以只使用一個循環:
res = []
for x in nums:
if x not in res:
res.append(x)
當然,這是非常昂貴的(O(N squared)),因此您可以使用輔助set
對其進行優化(我假設將res
的項目順序與nums
中的項目順序保持一致,否則為set(nums)
你願意嗎;-)...:
res = []
aux = set()
for x in nums:
if x not in aux:
res.append(x)
aux.add(x)
對於很長的列表(O(N) 而不是 N 平方),這要快得多。
編輯:在Python 2.5或2.6, vars()['_[1]']
實際上可能你想為角色工作self
(對於非嵌套listcomp)...這就是為什么我澄清有資格我的發言沒有記錄的、可靠的、穩定的方式來訪問“正在建立的列表”——那個奇特的、未記錄的“名稱” '_[1]'
(故意選擇不是一個有效的標識符;-)是“實現工件的頂點” "並且任何依賴於它的代碼都應該擺脫它的痛苦;-)。
其實你可以! 這個帶有解釋的例子有望說明如何。
定義遞歸示例以僅在 5 或更多時獲取數字,如果不是,則增加它並再次調用“檢查”函數。 重復這個過程直到達到 5,此時返回 5。
print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ]
結果:
[5, 5, 5, 5, 5, 6]
>>>
本質上,這兩個匿名函數以這種方式交互:
let f(g,x) = {
expression, terminal condition
g(g,x), non-terminal condition
}
let g(f,x) = {
expression, terminal condition
f(f,x), non-terminal condition
}
使 g,f 成為“相同”函數,除了在一個或兩個中添加一個子句,在該子句中修改參數以導致達到終止條件,然后以這種方式 g 成為 f(g,x) 的副本f 使它像:
f(g,x) = {
expression, terminal condition
{
expression, terminal condition,
g(g,x), non-terminal codition
}, non-terminal condition
}
您需要這樣做,因為您無法在執行時訪問匿名函數本身。
IE
(lambda f,v: somehow call the function again inside itself )(_,_)
所以在這個例子中,讓 A = 第一個函數,B = 第二個。 我們稱 A 傳遞 B 為 f,i 為 v。現在 B 本質上是 A 的副本,並且它是已傳遞的參數,您現在可以調用 B,就像調用 A 一樣。
這將生成列表中的階乘
print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ]
[1, 2, 6, 120, 720, 5040]
>>>
從Python 3.8
開始,並引入了賦值表達式 (PEP 572) ( :=
運算符),它提供了命名表達式結果的可能性,我們可以通過更新列表推導式中的變量來引用已經看到的項目:
# items = [1, 1, 2, 2, 3, 3, 4, 4]
acc = []; [acc := acc + [x] for x in items if x not in acc]
# acc = [1, 2, 3, 4]
這個:
acc
,它象征着已經看到的元素的運行列表acc
列表的一部分; 如果不:
acc
( acc := acc + [x]
)acc
的新值作為該項的映射值不確定這是否是您想要的,但您可以編寫嵌套列表推導式:
xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)]
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]]
從您的代碼示例中,您似乎只想簡單地消除重復項,您可以使用集合來做到這一點:
xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4]))
assert xs == [1, 2, 3, 4]
不。 它不起作用,在執行列表理解時沒有self
可以參考。
主要原因當然是列表推導式不是為此用途而設計的。
不。
但看起來您正在嘗試列出 nums 中的唯一元素。
你可以使用一set
:
unique_items = set(nums)
請注意, nums 中的項目需要是可散列的。
您還可以執行以下操作。 這是一個接近,因為我可以得到你的原始想法。 但這不如創建set
。
unique_items = []
for i in nums:
if i not in unique_items:
unique_items.append(i)
做這個:
nums = [1, 1, 2, 2, 3, 3, 4, 4]
set_of_nums = set(nums)
unique_num_list = list(set_of_nums)
甚至這個:
unique_num_list = sorted(set_of_nums)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.