关于python:如何在迭代时从列表中移除项?

How to remove items from a list while iterating?

我正在迭代Python中的元组列表,并试图在满足某些条件时删除它们。

1
2
3
for tup in somelist:
    if determine(tup):
         code_to_remove_tup

我应该用什么来代替code_to_remove_tup?我不知道如何以这种方式删除这个项目。


可以使用列表理解创建一个仅包含不想删除的元素的新列表:

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

或者,通过分配给切片somelist[:],可以改变现有列表,使其仅包含所需的项:

1
somelist[:] = [x for x in somelist if not determine(x)]

如果有其他需要反映变化的somelist的引用,这种方法可能会很有用。

除了理解,你还可以使用itertools。在Python 2中:

1
2
from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

或者在Python 3中:

1
2
from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)


建议列表理解的答案几乎是正确的——只是他们构建了一个全新的列表,然后给它起与旧列表相同的名称,因为他们没有适当地修改旧列表。这与选择删除不同,如@lennart的建议——它更快,但是如果您的列表是通过多个引用访问的,那么您只是重新放置其中一个引用,而不更改列表对象本身会导致细微的灾难性错误。

幸运的是,很容易获得列表理解的速度和就地更改所需的语义——只需代码:

1
somelist[:] = [tup for tup in somelist if determine(tup)]

注意与其他答案的细微区别:这一个不是分配给一个空名称-它分配给一个恰好是整个列表的列表切片,从而替换同一个python列表对象中的列表内容,而不是像其他答案一样重新放置一个引用(从以前的列表对象到新的列表对象)。


您需要获取列表的一个副本,并首先对其进行迭代,否则迭代将失败,并可能导致意外的结果。

例如(取决于列表的类型):

1
2
for tup in somelist[:]:
    etc....

一个例子:

1
2
3
4
5
6
7
8
9
10
11
>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]


1
2
3
for i in range(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

你需要向后走,否则就有点像锯掉你坐在上面的树枝。

python 2用户:用xrange替换range以避免创建硬编码列表


对于这样一个例子,最好的方法是列表理解

1
somelist = [tup for tup in somelist if determine(tup)]

如果您在执行比调用determine函数更复杂的操作,我更喜欢构建一个新的列表,并在执行过程中简单地将其附加到列表中。例如

1
2
3
4
5
6
newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

使用remove复制列表可能会使代码看起来更干净一些,如下面的某个答案所述。对于非常大的列表,您绝对不应该这样做,因为这涉及到首先复制整个列表,并对要删除的每个元素执行O(n)remove操作,使其成为O(n^2)算法。

1
2
3
4
for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

Python的官方教程4.2 2。。。。。。。"for语句"

http:/ / / / / 2 docs.python.org controlflow.html #是语句教程

这部分的文件,它是明确的:

  • 你需要做的副本的迭代中修改它
  • 它是单向的,与螺旋CT [:]符号

If you need to modify the sequence you are iterating over while inside the loop (for example to duplicate selected items), it is recommended that you first make a copy. Iterating over a sequence does not implicitly make a copy. The slice notation makes this especially convenient:

1
2
3
4
5
6
7
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

Python文档。2。。。。。。。"在它的声明"。

http:/ / / / / 2 docs.python.org参考化合物是_ stmts.html #

这部分的文件说,再一次,你要做一份好的去除,和当前的例子:

Note: There is a subtlety when the sequence is being modified by the loop (this can only occur for mutable sequences, i.e. lists). An internal counter is used to keep track of which item is used next, and this is incremented on each iteration. When this counter has reached the length of the sequence the loop terminates. This means that if the suite deletes the current (or a previous) item from the sequence, the next item will be skipped (since it gets the index of the current item which has already been treated). Likewise, if the suite inserts an item in the sequence before the current item, the current item will be treated again the next time through the loop. This can lead to nasty bugs that can be avoided by making a temporary copy using a slice of the whole sequence, e.g.,

1
2
for x in a[:]:
    if x < 0: a.remove(x)

然而,由于这一disagree与蛛网膜下腔出血(SAH)的实现,.remove()iterate整个列表中找到的值。

因此,所以:

  • 从头开始新的阵列,和背端:在.append()https:/ / / / / 895245 1207460 stackoverflow.com

    这个团队的效率,但由于它的无空间保持一份有效的阵列内的迭代过程。

  • 使用带有一del指数:https://///895245 1207485 stackoverflow.com

    这是更有效,因为它dispenses空间阵列的复制,但它是有效的,因为列表是不执行的时间,同时用动态数组。

    这意味着,所有的项目需要拆除后移回由一个项目,这是O(n)。

基本上你只是想走的更快,除非是.append()选项默认内存大的问题。

Python可以做更好?

Python的API,这样看来是可以改进的。例如,与它相比,其对应的listiterator Java,这使得它的清澈,你不能修改被迭代的列表迭代器本身除了与高效的方式给你,没有复制到操作系统的列表。

也许那是底层的理论假设是,Python列表是动态数组的支持,因此任何类型的去除效率会随时间nicer反正,Java接口与两个层次有LinkedListListIteratorArrayList和实现。

这似乎不是一个明确的链表型:是指在python python链表


对于那些喜欢函数式编程的人:

1
somelist[:] = filter(lambda tup: not determine(tup), somelist)

1
2
from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))


它也可能是创建一个新的智能化到当前列表中的项目是否符合所需的标准。

操作系统:

1
2
3
for item in originalList:
   if (item != badValue):
        newList.append(item)

具有和避免重新编码整个列表的名称:新项目

1
originalList[:] = newList

请注意,从Python的文档:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.


我需要用一个巨大的列表来完成这项工作,并且复制这个列表似乎很昂贵,特别是在我的例子中,与保留的项目相比,删除的数量是很少的。我采取了这种低级的方法。

1
2
3
4
5
6
7
8
9
array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

我不知道,与复制一个大列表相比,两个删除的效率有多高。如果您有任何见解,请发表评论。


此答案最初是针对已标记为重复的问题编写的:从python上的列表中删除坐标

代码中有两个问题:

1)当使用remove()时,您尝试移除整数,而需要移除元组。

2)for循环将跳过列表中的项目。

让我们来看看在执行代码时会发生什么:

1
2
3
4
5
6
7
8
>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
...
Traceback (most recent call last):
  File"<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

第一个问题是您将"a"和"b"同时传递给remove(),但remove()只接受一个参数。那么我们如何才能让remove()正确地处理您的列表呢?我们需要弄清楚您列表中的每个元素是什么。在这种情况下,每个都是一个元组。要看到这个,让我们访问列表中的一个元素(索引从0开始):

1
2
3
4
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

啊哈!l1的每个元素实际上是一个元组。所以这就是我们需要传递来移除()的内容。python中的元组非常简单,只需将值括在括号中就可以了。"a,b"不是一个元组,但"(a,b)"是一个元组。因此,我们修改您的代码并再次运行它:

1
2
# The remove line now includes an extra"()" to make a tuple out of"a,b"
L1.remove((a,b))

此代码运行时没有任何错误,但让我们看看它输出的列表:

1
L1 is now: [(1, 2), (5, 6), (1, -2)]

为什么(1,-2)仍然在您的列表中?事实证明,在使用循环迭代列表的同时修改列表是一个非常糟糕的主意,不需要特别注意。(1,-2)保留在列表中的原因是,在for循环的迭代之间,列表中每个项的位置都发生了更改。让我们看看如果我们向上面的代码提供一个更长的列表会发生什么:

1
2
3
L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

从结果中可以推断,每当条件语句的计算结果为true并且移除列表项时,循环的下一次迭代将跳过对列表中下一项的计算,因为其值现在位于不同的索引中。

最直观的解决方案是复制列表,然后迭代原始列表,只修改副本。您可以这样做:

1
2
3
4
5
6
7
8
9
L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now:", L1)

但是,输出将与之前相同:

1
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

这是因为当我们创建L2时,python实际上并没有创建新的对象。相反,它只是将l2引用到与l1相同的对象。我们可以用"is"来验证这一点,它与"equals"(==)不同。

1
2
3
>>> L2=L1
>>> L1 is L2
True

我们可以使用copy.copy()生成一个真正的副本。然后一切按预期工作:

1
2
3
4
5
6
7
8
9
10
import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

最后,还有一个比制作一个全新的L1副本更干净的解决方案。reversed()函数:

1
2
3
4
5
6
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now:", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

不幸的是,我无法充分描述revered()的工作方式。当一个列表传递给它时,它返回一个"listReverseIterator"对象。出于实际目的,您可以将其视为创建其论点的反向副本。这是我推荐的解决方案。


您可能希望使用可用的filter()作为内置的。

有关详细信息,请查看此处


如果您想在迭代过程中执行其他操作,那么最好同时获取索引(这可以保证您能够引用它,例如,如果您有一个dict列表)和实际的列表项内容。

1
2
3
4
5
6
inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerate允许您立即访问该项和索引。reversed是这样的,您以后要删除的索引不会改变。


一个可能的解决方案,如果您不仅想删除某些内容,而且还想在单个循环中对所有元素执行某些操作,那么它很有用:

1
2
3
4
5
6
7
8
9
alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1


您可以尝试反向循环,因此对于某些列表,您可以执行如下操作:

1
2
3
4
5
6
7
8
9
list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

这样索引就可以对齐,并且不会受到列表更新的影响(不管是否弹出cur元素)。


TLDR:

我写了一个图书馆,允许你这样做:

1
2
3
4
5
6
7
8
from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without"breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

如果可能的话,最好使用另一种方法,在迭代ITerable时不需要修改它,但是对于某些算法,它可能不是那么直接的。因此,如果您确定您确实想要原始问题中描述的代码模式,那么这是可能的。

应该处理所有可变序列,而不仅仅是列表。

完全回答:

编辑:这个答案中的最后一个代码示例给出了一个用例,说明为什么有时您可能希望就地修改列表,而不是使用列表理解。答案的第一部分是如何就地修改数组的教程。

解决方法是从senderle的这个答案(对于相关问题)开始的。这解释了在遍历已修改的列表时如何更新数组索引。下面的解决方案旨在正确跟踪数组索引,即使修改了列表。

从这里下载fluidIter.pyhttps://github.com/alanbacon/FluidIterator只是一个文件,不需要安装git。没有安装程序,因此您需要确保文件在自己的python路径中。代码是为python 3编写的,没有在python 2上测试过。

1
2
3
4
5
6
7
8
9
10
from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                      
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL))
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

这将产生以下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

上面我们在流体列表对象上使用了pop方法。其他常见的可重复的方法也被实施,如del fluidL[i].remove.insert.append.extend。还可以使用切片修改列表(没有实现sortreverse方法)。

唯一的条件是,如果在任何时候fluidLl被重新分配给不同的列表对象,那么您只能在适当的位置修改列表,代码将不起作用。原来的fluidL对象仍将被for循环使用,但将超出我们修改的范围。

1
2
fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

如果要访问列表的当前索引值,则不能使用枚举,因为这只计算for循环已运行的次数。相反,我们将直接使用迭代器对象。

1
2
3
4
5
6
7
8
9
10
11
12
fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

这将输出以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

FluidIterable类只是为原始列表对象提供了一个包装器。原始对象可以作为流体对象的属性访问,如下所示:

1
originalList = fluidArr.fixedIterable

更多示例/测试可在fluidIter.py底部的if __name__ is"__main__":部分找到。这些值得一看,因为它们解释了在各种情况下发生的事情。例如:使用一个切片替换列表中的大部分。或者在嵌套for循环中使用(和修改)相同的iterable。

正如我前面所说:这是一个复杂的解决方案,它会损害代码的可读性,并使调试更加困难。因此,其他解决方案,如大卫拉兹尼克回答中提到的清单理解,应该首先考虑。也就是说,我发现这个类对我有用的时候,比跟踪需要删除的元素的索引更容易使用。

编辑:正如评论中所提到的,这个答案并没有真正提出一个问题,这个方法为这个问题提供了解决方案。我将尝试在这里解决这个问题:

列表理解提供了一种生成新列表的方法,但是这些方法倾向于孤立地查看每个元素,而不是将列表的当前状态作为一个整体。

1
newList = [i for i in oldList if testFunc(i)]

但是,如果testFunc的结果依赖于已经添加到newList中的元素呢?或者,下一个可能添加的元素仍在oldList中?也许还有一种方法可以使用列表理解,但它将开始失去它的优雅,对我来说,在适当的位置修改列表更容易。

下面的代码是遭受上述问题的算法的一个例子。该算法将减少一个列表,使任何元素都不是任何其他元素的倍数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

输出和最终缩减列表如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]


这里的大多数答案都希望您创建列表的副本。我有一个用例,其中的列表很长(11000个项目),所以最好继续减少列表。

首先,用while循环替换foreach循环,

1
2
3
4
5
6
i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1

在if块中,i的值没有更改,因为删除旧项后,您希望从同一索引中获取新项的值。


我需要类似的东西在我的案例和问题是我需要记忆的数据集对象中的多表合并后的东西,做一些与他们的新的对象和需要,摆脱每一项都被合并以避免他们duplicating吹起来的记忆。在我的案例中,有对象的列表,而不是一本字典的精细加工。

` ` `

1
2
3
4
5
6
7
8
9
k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

` ` `


其他的答案是正确的,从正在迭代的列表中删除通常是一个坏主意。反向迭代避免了这些陷阱,但是遵循这样做的代码要困难得多,因此通常最好使用列表理解或filter

但是,有一种情况是可以安全地从正在迭代的序列中删除元素:如果在迭代时只删除一个项。这可以使用returnbreak来确保。例如:

1
2
3
4
5
for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

当您对满足某些条件的列表中的第一个项目执行一些具有副作用的操作,然后在之后立即从列表中删除该项目时,这通常比列表理解更容易理解。


最有效的方法是列表理解,很多人都会给出自己的例子,当然,这也是通过filter得到iterator的一个好方法。

Filter receives a function and a sequence. Filter applies the passed function to each element in turn, and then decides whether to retain or discard the element depending on whether the function return value is True or False.

有一个例子(从元组中得到赔率):

1
2
list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]

注意:您也不能处理迭代器。迭代器有时比序列更好。


我可以想出三种方法来解决你的问题。例如,我将创建一个元组somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]的随机列表。我选择的条件是sum of elements of a tuple = 15。在最后一个列表中,我们将只包含总和不等于15的元组。

我选择的是一个随机选择的例子。请随意更改元组列表和我选择的条件。

方法1.>使用您建议的框架(其中一个在for循环中填充代码)。我在del中使用一个小代码来删除一个满足上述条件的元组。但是,如果两个连续放置的元组满足给定条件,则此方法将缺少一个元组(满足上述条件)。

1
2
3
4
5
6
for tup in somelist:
    if ( sum(tup)==15 ):
        del somelist[somelist.index(tup)]

print somelist
>>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]

方法2.>构造一个新的列表,其中包含不满足给定条件的元素(元组)(这与删除满足给定条件的列表元素相同)。代码如下:

1
2
3
4
newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]

print newlist1
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

方法3.>找到满足给定条件的索引,然后使用与这些索引对应的移除元素(元组)。下面是代码。

1
2
3
4
5
indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]

print newlist2
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

方法1和方法2比方法3快。方法2和方法3比方法1更有效。我更喜欢方法2。对于上述示例,time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7


如果稍后使用新列表,只需将elem设置为none,然后在后面的循环中判断它,如下所示

1
2
3
4
5
6
for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

这样,你就不需要复制列表了,而且更容易理解。


对于任何可能非常大的项目,我都使用以下内容。

1
2
3
4
5
6
7
8
import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

这应该比其他任何事情都快得多。


在某些情况下,当您不仅仅是一次过滤一个列表项时,您希望在迭代时更改迭代。

这里有一个示例,其中预先复制列表是不正确的,反向迭代是不可能的,并且列表理解也不是一个选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
""" Sieve of Eratosthenes"""

def generate_primes(n):
   """ Generates all primes less than n."""
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p

现在您想要创建一个列表的副本,这样当您迭代和删除该列表中满足特定条件的元组时,可以将其作为引用。

然后,它取决于您希望输出的列表类型,无论是已删除元组的列表还是未删除的元组的列表。

正如大卫指出的,我建议列表理解来保留不想删除的元素。

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