這段代碼是否有潛在危險?它會混淆內部和外部迭代嗎?Python:從循環迭代器的內部和外部移除項目
for a in listA:
for b in listB:
if [... something...]:
... something else...
listA.remove(a)
listB.remove(b)
break
這段代碼是否有潛在危險?它會混淆內部和外部迭代嗎?Python:從循環迭代器的內部和外部移除項目
for a in listA:
for b in listB:
if [... something...]:
... something else...
listA.remove(a)
listB.remove(b)
break
更改正在迭代的序列通常是Python中的反模式。雖然可以在特定情況下圍繞它跳舞,但最好查看是否可以構建僅包含所需項目的新列表(或字典)。
實際上,我會同時刪除'a'和'b',然後調用'break',它會跳出內循環並移動到'listA'中的下一個元素。 – 2013-02-15 16:25:57
啊,錯過了休息。你是對的,我會編輯我的答案(總體原則仍然適用)。 – jknupp 2013-02-15 16:28:41
這段代碼有潛在危險嗎?依靠。迭代時減小序列的大小會產生意想不到的行爲。
考慮這個例子
listA = [1,2,3,4]
>>> for a in listA:
listA.remove(a)
print a
因爲,在刪除的項目,全部超越它的項目,朝左,該項目是你所想象迭代會自動移動到下一個元素推
第一次迭代:
listA = [1,2,3,4]
^
|
_____________|
listA.remove(a)
listA = [2,3,4]
^
|
_____________|
print a
(outputs) 1
第二次迭代:
listA = [2,3,4]
^
|
_______________|
listA.remove(a)
listA = [2,4]
^
|
_______________|
print a
(outputs) 3
第三次迭代:
listA = [2,4]
^
|
_________________|
(Exits the Loop)
哦,所以我實際上是在跳項目,這正是我所遇到的行爲。非常感謝你的解釋。 – 2013-02-15 16:29:30
我同意jknupp - 在列表中刪除的項目可以比創建一個新的更貴。然而,另一個訣竅是向後做:
>>> l = range(5)
>>> for a in reversed(l):
... print a
... l.remove(a)
...
4
3
2
1
0
嚴。將顛倒創建列表的本地副本?否則,我沒有看到差異。 – 2013-02-15 17:20:10
不,reverse()創建一個反向迭代器。它的名字有點誤導,但至少它不太詳細。通過向後迭代,您已經傳遞了將由remove()取代的所有元素。 – tdelaney 2013-02-15 19:50:38
是的,是的:它可能不會像你想要的那樣工作。請參閱http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python – Emily 2013-02-15 16:20:34
也許試試這個:'爲b在listb [:]:'它只會做一個列表的副本,你可以從你的原始列表中刪除。 – 2013-02-15 16:27:32
是的,這聽起來比通過列表理解完成所有事情要好得多。我在上面的「......別的東西」中做了很多事情,壓縮上面鏈接中建議的所有內容會有點麻煩。 – 2013-02-15 16:32:07