[英]Swapping List Elements During Iteration
我在幾個地方讀到過,在迭代期間修改數組/列表是不好的做法。 然而,許多常見的算法似乎可以做到這一點。 例如冒泡排序、插入排序和下面的示例,用於查找對列表進行排序所需的最小交換次數。
在迭代期間交換列表項是否是規則的例外? 如果是,為什么?
在這方面, enumerate
和簡單for i in range(len(arr))
循環之間有什么區別嗎?
def minimumSwaps(arr):
ref_arr = sorted(arr)
index_dict = {v: i for i,v in enumerate(arr)}
swaps = 0
for i,v in enumerate(arr):
print("i:", i, "v:", v)
print("arr: ", arr)
correct_value = ref_arr[i]
if v != correct_value:
to_swap_ix = index_dict[correct_value]
print("swapping", arr[to_swap_ix], "with", arr[i])
# Why can you modify list during iteration?
arr[to_swap_ix],arr[i] = arr[i], arr[to_swap_ix]
index_dict[v] = to_swap_ix
index_dict[correct_value] = i
swaps += 1
return swaps
arr = list(map(int, "1 3 5 2 4 6 7".split(" ")))
assert minimumSwaps(arr) == 3
遍歷數組時不應修改數組,因為迭代器無法處理更改。 但是還有其他方法可以通過數組 go,而不使用迭代器。
這是使用迭代器:
for index, item in enumerate(array):
# don't modify array here
這是沒有迭代器的:
for index in range(len(array)):
item = array[index]
# feel free to modify array, but make sure index and len(array) are still OK
如果在修改數組時需要修改長度和索引,請更“手動”進行:
index = 0
while index < len(array):
item = array[index]
# feel free to modify array and modify index if needed
index += 1
修改列表中的項目有時可能會產生意想不到的結果,但如果您知道效果,那完全沒問題。 這不是不可預測的。
您需要了解它不是您正在迭代的原始列表的副本。 下一項始終是列表中下一個索引上的項。 因此,如果您在迭代器到達它之前更改索引中的項目,迭代器將產生新值。
這意味着,例如,如果您打算通過將 index+1 處的項目設置為 enumerate() 產生的當前值,將所有項目上移一個索引。 然后,您將得到一個列表,該列表完全填充了最初位於索引 0 上的項目。
a = ['a','b','c','d']
for i, v in enumerate(a):
next_i = (i + 1) % len(a)
a[next_i] = v
print(a) # prints ['a', 'a', 'a', 'a']
而且,如果您在迭代時將項目追加和插入到列表中,您可能永遠不會到達終點。
在您的示例中,正如您在許多算法中指出的那樣,例如組合和排序,它是更改即將到來的項目的算法的一部分。
像for i in range(len(arr))
這樣的范圍內的迭代器不會適應原始列表中的變化,因為范圍是在開始之前創建的並且是不可變的。 因此,如果列表的開頭長度為 4,則無論列表長度如何變化,循環都會嘗試精確迭代 4 次。
# This is probably a bad idea
for i in range(len(arr)):
item = arr[i]
if item == 0:
arr.pop()
# This will work (don't ask for a use case)
for i, item in enumerate(arr):
if item == 0:
arr.pop()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.