在 Python 中迭代时从列表中删除特定索引

Remove a specific index from a list while iterating in Python

我通过以下方式学习了如何从 here 迭代时从列表中删除项目:

somelist = [x for x in somelist if determine(x)]

此外,如何在迭代时从列表中删除特定索引?例如,

lists = list() # a list of lists

for idx, line in enumerate(lists):
    if idx > 0:
        cur_val = line[0] # value of current line
        prev_val = lists[idx-1][0] # value of previous line

        if prev_val == cur_val :
            del lists[idex-1] # IndexError: list index out of range

您可以使用列表理解生成相同的东西:

somelist = [i for idx, i in enumerate(lists) if i[0] != lists[idx][0]]

根据任何文档,基本上不支持您的尝试。通常,除非文档明确说明可以,否则您不应在迭代时修改容器。如果它 "seems to work" 没有帮助,因为您只是利用了您正在使用的实现版本中的某些行为,但该行为可能会更改,恕不另行通知(破坏您的程序)。

您需要做的是将修改与迭代分开。使用列表理解是实现此目的的一种方法,但基本上你在做同样的事情。

有几个变体,您可以复制数据并遍历它并修改原始数据。或者您在迭代原件之前制作副本并修改副本,然后更新原件。还有一种变体,您可以在迭代期间构建副本,然后更新原始版本。

此外,您的示例存在缺陷,因为您没有考虑到修改会影响修改后 list 中的正确索引。例如,如果您有列表 [1, 1, 2, 2, 3, 3],那么当您删除重复项 1s 和 2s 并检测到重复项 3s 时,您就有了列表 [1, 2, 3, 3],但是当您找到重复的 3s 时,您会在索引 45 处找到它们,但删除后它们位于索引 23 相反。

lists = list() # a list of lists

cur = 0 # index in the modified list
for idx, line in list(enumerate(lists)): # make a copy of the original
    if idx > 0:
        cur_val = line[0] # value of current line
        prev_val = lists[idx-1][0] # value of previous line

        if prev_val == cur_val:
            del lists[cur-1] # IndexError: list index out of range
        else:
            cur += 1
    else:
        cur += 1

修改副本的方案基本相同,迭代构建副本的方案略有不同

lists = list() # a list of lists

tmp = []
for idx, line in enumerate(lists): # make a copy of the original
    if idx > 0:
        cur_val = line[0] # value of current line
        prev_val = lists[idx-1][0] # value of previous line

        if prev_val != cur_val:
            tmp.append(line)
    else:
        tmp.append( line )

 lists[:] = tmp

最后一行是原点更新的地方,否则循环通过将那些要保留的元素附加到 tmp(而不是复制所有元素然后删除那些不保留的元素)来工作。