Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在迭代时从列表中删除项?_Python_Iteration - Fatal编程技术网

Python 如何在迭代时从列表中删除项?

Python 如何在迭代时从列表中删除项?,python,iteration,Python,Iteration,我在Python中迭代元组列表,如果它们满足某些条件,我将尝试删除它们 for tup in somelist: if determine(tup): code_to_remove_tup 我应该用什么来代替code\u来删除安装程序?我不知道如何以这种方式删除该项。您需要先复制一份列表并对其进行迭代,否则迭代将失败,结果可能会出乎意料 例如(取决于列表的类型): 例如: >>> somelist = range(10) >>> f

我在Python中迭代元组列表,如果它们满足某些条件,我将尝试删除它们

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

我应该用什么来代替
code\u来删除安装程序
?我不知道如何以这种方式删除该项。

您需要先复制一份列表并对其进行迭代,否则迭代将失败,结果可能会出乎意料

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

例如:

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

对于这样一个例子,您最好的方法是

如果您正在执行比调用
determinate
函数更复杂的操作,我更喜欢构建一个新列表,并在执行时简单地将其添加到列表中。比如说

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)
算法

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

您可以使用列表理解创建一个新列表,其中只包含您不想删除的元素:

somelist = [x for x in somelist if not determine(x)]
或者,通过分配给切片
somelist[:]
,可以改变现有列表,使其仅包含所需的项目:

somelist[:] = [x for x in somelist if not determine(x)]
如果对
somelist
的其他引用需要反映这些更改,那么这种方法可能很有用

您还可以使用
itertools
,而不是理解。在Python 2中:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)
或者在Python 3中:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)
你需要向后走,否则就有点像锯掉你坐的树枝:-)


Python 2用户:将
range
替换为
xrange
,以避免为喜欢函数式编程的用户创建硬编码列表:

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


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

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

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

请注意与其他答案的细微差别:这一答案并不是指定给一个单名,而是指定给恰好是整个列表的列表片,从而替换同一个Python列表对象中的列表内容,而不仅仅是重新放置一个引用(从上一个列表对象到新列表对象)与其他答案一样。

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


要了解更多详细信息,如果您想在迭代过程中执行任何其他操作,最好同时获取索引(这保证您能够引用它,例如,如果您有一个dict列表)和实际的列表项内容

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
允许您立即访问项目和索引<代码>反向是为了使您稍后要删除的索引不会在您身上更改

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

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)

这样,索引就对齐了,并且不会受到列表更新的影响(无论您是否使用pop cur元素)。

解决方法概述

要么:

  • 使用链表实现/滚动您自己的

    链表是支持高效项目删除的适当数据结构,不会强制您进行空间/时间权衡

    CPython
    list
    是用as实现的,as不是支持删除的好数据类型

    但是,标准库中似乎没有链接列表:

  • 从头开始创建一个新的
    list()
    ,并在末尾添加
    .append()
    ,如所述:

    这会节省时间,但节省空间,因为它会在迭代期间保留阵列的额外副本

  • del
    与下列索引一起使用:

    这会更节省空间,因为它分配了数组副本,但时间效率较低,因为从动态数组中删除需要将以下所有项向后移动一个,即O(N)

一般来说,如果你做得又快又脏,并且不想添加自定义的
LinkedList
类,那么默认情况下你只想选择更快的
.append()
选项,除非内存是一个大问题

官方Python 2教程4.2。“对于声明”

本部分文件明确指出:

  • 您需要制作迭代列表的副本来修改它
  • 一种方法是使用切片表示法
    [:]
如果需要在循环内部修改正在迭代的序列(例如复制选定项),建议您首先进行复制。在序列上迭代不会隐式生成副本。切片表示法特别方便:

>>> 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文档7.3。“for语句”

文档的这一部分再次指出,您必须制作一份副本,并给出了一个实际的删除示例:

注意:当循环修改序列时有一个微妙之处(这只能发生在可变序列,即列表中)。内部计数器用于跟踪下一个使用哪个项,并且在每次迭代中递增。当该计数器达到序列长度时,循环终止。这意味着如果套件删除
somelist[:] = [tup for tup in somelist if determine(tup)]
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]
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)
>>> 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']
for x in a[:]:
    if x < 0: a.remove(x)
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
for item in originalList:
   if (item != badValue):
        newList.append(item)
originalList[:] = newList
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'
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))
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]
fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK
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))
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]
originalList = fluidArr.fixedIterable
newList = [i for i in oldList if testFunc(i)]
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)
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]
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
>>> 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)
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
L1 is now: [(1, 2), (5, 6), (1, -2)]
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)]
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)
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
>>> L2=L1
>>> L1 is L2
True
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 = [(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)]
array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1
for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break
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)
""" 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
i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1
list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]
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)]
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)]
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)]
for i in li:
    i = None

for elem in li:
    if elem is None:
        continue
[5, 7, 13, 29, 65, 91]
lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6
lis.remove(y)
lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5
ite = lis #dont do it will reference instead copy
[5, 7, 13, 29]
i = 0
length = len(list1)

while i < length:
    if condition:
        list1.remove(list1[i])
        i -= 1
        length -= 1

    i += 1