简体   繁体   English

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

[英]Remove a specific index from a list while iterating in Python

I learn how to remove items from a list while iterating from here by: 我学会了如何从一个列表,而从迭代中删除项目在这里通过:

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

Further, how do I remove a specific index from a list while iterating? 此外,如何在迭代时从列表中删除特定索引? For instance, 例如,

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

Basically your attempt is not supported according to any documentation. 基本上,任何文档均不支持您的尝试。 In general you should not modify a container while iterating unless the documentation explicitly says that you can. 通常,除非文档明确说明可以,否则在迭代时不应修改容器。 It doesn't help if it "seems to work" since you then just exploiting some behavior in the version of the implementation you're using, but that behavior can change without prior notice (breaking your program). 如果它“似乎可以正常工作”,这无济于事,因为您只是在利用所使用的实现版本中的某些行为即可,但是这种行为可以更改而无需事先通知(破坏程序)。

What you need to do is making the modification separate from the iteration. 您需要做的是使修改与迭代分开。 Using list comprehension is one way to achieve this, but basically you're doing the same thing. 使用列表理解是实现此目的的一种方法,但基本上,您正在做相同的事情。

There's a few variants, either you make a copy of the data and iterate through that and modify the original. 有几种变体,您可以复制数据并进行遍历并修改原始数据。 Or you make a copy before iterating the original and modify the copy and then updates the original. 或者,您在遍历原件之前先进行复印,然后修改副本,然后更新原件。 There's also the variant where you build the copy during iteration and then update the original. 还有一种变体,您可以在迭代过程中构建副本,然后更新原始副本。

In addition your example is flawed because you don't take into account that modification affects the proper index in the modified list . 此外,您的示例存在缺陷,因为您没有考虑到修改会影响修改后的list的适当索引。 For example if you have the list [1, 1, 2, 2, 3, 3] , then when you've removed the duplicates 1 s and 2 s and detect duplicate 3 s you have the list [1, 2, 3, 3] , but when you find the duplicate 3 s you find these at index 4 and 5 , but after the deletion they are at index 2 and 3 instead. 例如,如果您具有列表[1, 1, 2, 2, 3, 3] ,那么当您删除重复项1 s和2 s并检测到重复项3 s时,您就拥有了列表[1, 2, 3, 3] ,但是当您找到重复的3时,您将在索引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

The solution where you modify a copy instead is basically the same, but the solution where you build the copy during iteration is a bit different. 修改副本的解决方案基本上是相同的,但是在迭代过程中生成副本的解决方案则有所不同。

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

The last line is where the origin is updated, otherwise the loop works by appending those elements that are to be kept to tmp (instead of copying all and then remove those that's not to be kept). 最后一行是更新原点的地方,否则循环通过将要保留的元素附加到tmp (而不是复制所有元素然后删除不保留的元素)。

您可以使用列表推导产生相同的结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM