Python 如何在迭代时从列表中删除项?
我在Python中迭代元组列表,如果它们满足某些条件,我将尝试删除它们Python 如何在迭代时从列表中删除项?,python,iteration,Python,Iteration,我在Python中迭代元组列表,如果它们满足某些条件,我将尝试删除它们 for tup in somelist: if determine(tup): code_to_remove_tup 我应该用什么来代替code\u来删除安装程序?我不知道如何以这种方式删除该项。您需要先复制一份列表并对其进行迭代,否则迭代将失败,结果可能会出乎意料 例如(取决于列表的类型): 例如: >>> somelist = range(10) >>> f
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
是用as实现的,as不是支持删除的好数据类型 但是,标准库中似乎没有链接列表:list
- 从头开始创建一个新的
,并在末尾添加list()
,如所述: 这会节省时间,但节省空间,因为它会在迭代期间保留阵列的额外副本.append()
- 将
与下列索引一起使用: 这会更节省空间,因为它分配了数组副本,但时间效率较低,因为从动态数组中删除需要将以下所有项向后移动一个,即O(N)del
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