簡體   English   中英

在迭代期間交換列表元素

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

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