我正在遍历Python中的元组列表,并尝试在满足特定条件的情况下将其删除。
for tup in somelist:
if determine(tup):
code_to_remove_tup
我应该用什么代替code_to_remove_tup
? 我不知道如何以这种方式删除项目。
#1楼
您需要获取列表的副本并首先对其进行迭代,否则迭代将失败,并可能导致意外结果。
例如(取决于列表的类型):
for tup in somelist[:]:
etc....
一个例子:
>>> 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
[]
#2楼
此类示例的最佳方法是列表理解
somelist = [tup for tup in somelist if determine(tup)]
如果您要做的事情比调用determine
函数还要复杂,我更喜欢构造一个新列表,然后随便添加它。 例如
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)
#3楼
您可以使用列表推导来创建一个仅包含您不想删除的元素的新列表:
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)
#4楼
for i in range(len(somelist) - 1, -1, -1):
if some_condition(somelist, i):
del somelist[i]
您需要向后走,否则就像从您坐在的树枝上砍掉它一样:-)
Python 2用户:用xrange
替换range
以避免创建硬编码列表
#5楼
对于那些喜欢函数式编程的人:
somelist[:] = filter(lambda tup: not determine(tup), somelist)
要么
from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))
#6楼
暗示列表理解的答案几乎是正确的-除了它们会建立一个全新的列表,然后为其命名与旧列表相同,而不会在原地修改旧列表。 这与@Lennart的建议中的选择性删除操作不同-速度更快,但是如果通过多个引用访问列表,则事实是您只是在重新放置其中一个引用而不更改列表对象本身可能会导致微妙的灾难性错误。
幸运的是,获得列表理解的速度和就地变更所需的语义非常容易,只需编写代码即可:
somelist[:] = [tup for tup in somelist if determine(tup)]
请注意与其他答案的细微差别:这不是分配给裸名-而是分配给恰好是整个列表的列表切片,从而替换同一Python列表对象中的列表内容 ,而不仅仅是重新放置一个引用(从先前的列表对象到新的列表对象),就像其他答案一样。
#7楼
如果要在迭代过程中执行其他任何操作,最好同时获得索引(这可以保证您能够引用它,例如,如果您有字典列表)和实际的列表项内容。
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
是,这样您以后要删除的索引不会改变。
#8楼
您可以尝试反向进行循环,因此对于some_list,您将执行以下操作:
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元素)。
#9楼
官方Python 2教程4.2。 “用于声明”
https://docs.python.org/2/tutorial/controlflow.html#for-statements
这部分文档清楚地表明:
- 您需要复制迭代列表以对其进行修改
- 一种方法是使用切片符号
[:]
如果需要修改循环中要迭代的序列(例如,复制选定的项目),建议您首先进行复制。 遍历序列不会隐式地创建副本。 切片符号使这特别方便:
>>> 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声明”
https://docs.python.org/2/reference/compound_stmts.html#for
这部分文档再次说明您必须进行复制,并提供了一个实际的删除示例:
注意:循环修改序列时有一个微妙之处(这仅适用于可变序列,即列表)。 内部计数器用于跟踪下一个要使用的项目,并且在每次迭代时都会递增。 当该计数器达到序列的长度时,循环终止。 这意味着,如果套件从序列中删除当前(或上一个)项目,则下一个项目将被跳过(因为它获取已被处理的当前项目的索引)。 同样,如果套件在当前项目之前按顺序插入一个项目,则下次通过循环再次处理当前项目。 这可能会导致讨厌的错误,可以通过使用整个序列的一部分进行临时复制来避免这些错误,例如,
for x in a[:]: if x < 0: a.remove(x)
但是,我不同意此实现,因为.remove()
必须迭代整个列表以查找值。
最佳解决方法
要么:
从头开始创建新数组,然后在末尾返回
.append()
: https : //stackoverflow.com/a/1207460/895245这种时间效率高,但空间效率低,因为它在迭代期间会保留阵列的副本。
使用带有索引的
del
: https : //stackoverflow.com/a/1207485/895245由于它分配了数组副本,因此空间使用效率更高,但由于CPython列表是使用动态数组实现的,因此时间效率较低。
这意味着要删除项目,需要将所有随后的项目后退一个,即O(N)。
通常,除非内存是一个大问题,否则默认情况下,您只想默认使用更快的.append()
选项。
Python可以做得更好吗?
似乎可以改进此特定的Python API。 例如,将其与Java的ListIterator进行比较 ,可以很清楚地知道,除了迭代器本身之外,您无法修改要迭代的列表,并且为您提供了无需复制列表的高效方法。
也许基本理由是,Python列表被假定为动态数组支持,并且因此任何类型的去除将是时间低效反正,同时Java有既具有更好的接口层次结构ArrayList
和LinkedList
的实现方式ListIterator
。
Python stdlib中似乎也没有明确的链接列表类型: Python链接列表
#10楼
我需要做类似的事情,在我的情况下,问题是内存-我需要将列表中的多个数据集对象合并,然后再对它们做一些事情,作为一个新对象,并且需要摆脱要合并到的每个条目避免重复所有操作并浪费内存。 就我而言,将对象放在字典中而不是列表中可以很好地工作:
```
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
```
#11楼
如果当前列表项符合期望的条件,那么也只创建一个新列表可能很聪明。
所以:
for item in originalList:
if (item != badValue):
newList.append(item)
并且避免必须使用新的列表名称重新编码整个项目:
originalList[:] = newList
注意,来自Python文档:
copy.copy(x)返回x的浅表副本。
copy.deepcopy(x)返回x的深层副本。
#12楼
TLDR:
我写了一个库,使您可以执行此操作:
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'
如果可能的话,最好使用另一种方法,该方法不需要在迭代时修改可迭代对象,但是对于某些算法,可能不是那么简单。 因此,如果您确定确实希望原始问题中描述的代码模式,则可以。
应该适用于所有可变序列,而不仅仅是列表。
完整答案:
编辑:此答案中的最后一个代码示例给出了一个用例, 说明了为什么有时您可能想在适当位置修改列表而不是使用列表理解。 答案的第一部分用作如何在适当位置修改数组的教程。
从senderle的此答案(针对相关问题)可以得出解决方案。 这说明了在遍历已修改的列表时如何更新数组索引。 即使解决方案列表被修改,下面的解决方案旨在正确跟踪数组索引。
从这里 https://github.com/alanbacon/FluidIterator
下载fluidIter.py
,它只是一个文件,因此无需安装git。 没有安装程序,因此您需要确保该文件位于您自己的python路径中。 该代码是为python 3编写的,未经python 2的测试。
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]
上面我们在流体列表对象上使用了pop
方法。 其他常见的可迭代方法也实现,诸如del fluidL[i]
.remove
, .insert
, .append
, .extend
。 也可以使用切片来修改列表(未实现sort
和reverse
方法)。
唯一的条件是,您必须仅在适当位置修改列表,如果在任何时候将fluidL
或l
重新分配给其他列表对象,代码将无法正常工作。 原始的fluidL
对象仍将由for循环使用,但将超出我们的修改范围。
即
fluidL[2] = 'a' # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8] # is not OK
如果要访问列表的当前索引值,则不能使用枚举,因为它仅计算for循环已运行了多少次。 相反,我们将直接使用迭代器对象。
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]
FluidIterable
类仅提供原始列表对象的包装。 可以将原始对象作为流体对象的属性进行访问,如下所示:
originalList = fluidArr.fixedIterable
if __name__ is "__main__":
fluidIter.py
在fluidIter.py
底部的更多示例/测试中可以找到。 这些值得一看,因为它们解释了在各种情况下会发生什么。 例如:使用切片替换列表的大部分。 或在嵌套for循环中使用(并修改)相同的可迭代对象。
就像我刚开始所说的那样:这是一个复杂的解决方案,将损害代码的可读性,并使调试更加困难。 因此,应该首先考虑其他解决方案,例如David Raznick的答案中提到的列表理解。 话虽这么说,但我发现此类对我很有用,并且比跟踪需要删除的元素的索引更容易使用。
编辑:如评论中所述,此答案并未真正提出此方法可提供解决方案的问题。 我将在这里尝试解决:
列表理解提供了一种生成新列表的方法,但是这些方法倾向于孤立地查看每个元素,而不是整个列表的当前状态。
即
newList = [i for i in oldList if testFunc(i)]
但是,如果testFunc
的结果取决于已经添加到newList
的元素怎么办? 还是可能oldList
添加到oldList
中的元素? 仍然可能有一种使用列表理解的方法,但是它将开始失去它的优雅性,对我来说,就地修改列表更容易。
下面的代码是遭受上述问题的算法的一个示例。 该算法将减少列表,以使任何元素都不是其他任何元素的倍数。
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]
#13楼
一种可能的解决方案,如果您不仅要删除某些内容,而且还希望在单个循环中对所有元素执行某些操作,则很有用:
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
#14楼
此答案最初是为回答一个问题而编写的,此问题已被标记为重复: 从python列表中删除坐标
您的代码中有两个问题:
1)使用remove()时,您尝试删除整数,而您需要删除元组。
2)for循环将跳过您列表中的项目。
让我们看一下执行代码时发生的情况:
>>> 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开始):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
啊哈! L1的每个元素实际上都是一个元组。 这就是我们需要传递给remove()的东西。 python中的元组非常简单,只需将值括在括号中即可。 “ a,b”不是元组,但是“(a,b)”是元组。 因此,我们修改您的代码并再次运行:
# 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)]
为什么(1,-2)仍在您的列表中? 事实证明,在使用循环迭代列表时修改列表是一个非常糟糕的主意,无需特别注意。 (1,-2)保留在列表中的原因是列表中每个项目的位置在for循环的迭代之间更改。 让我们看看如果将上面的代码输入更长的列表会发生什么:
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并删除列表项时,循环的下一次迭代将跳过对列表中下一项的评估,因为它的值现在位于不同的索引处。
最直观的解决方案是复制列表,然后遍历原始列表并仅修改副本。 您可以尝试这样做:
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时,python实际上并未创建新对象。 相反,它仅将L2引用为与L1相同的对象。 我们可以使用“ is”来验证这一点,而“ is”不同于“等于”(==)。
>>> L2=L1
>>> L1 is L2
True
我们可以使用copy.copy()制作一个真实的副本。 然后一切都按预期工作:
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()函数:
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)]
不幸的是,我无法充分描述reversed()的工作方式。 当列表传递给它时,它返回一个“ listreverseiterator”对象。 出于实际目的,您可以将其视为创建其参数的反向副本。 这是我推荐的解决方案。
#15楼
我需要使用大量列表来完成此操作,并且复制列表似乎很昂贵,尤其是因为在我的情况下,与保留的项目相比,删除的数量很少。 我采用了这种低级方法。
array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
if someTest(array[i]):
del array[i]
arraySize -= 1
else:
i += 1
我不知道几个删除相比复制大型列表的效率如何。 如果您有任何见解,请发表评论。
#16楼
您立即想创建列表的副本,以便在遍历和删除满足特定条件的列表中的元组时可以将其作为参考。
然后,这取决于您要用于输出的列表类型,究竟是已删除元组的列表还是未删除元组的列表。
正如David指出的那样,我建议您理解列表,以保留不想删除的元素。
somelist = [x for x in somelist if not determine(x)]
#17楼
您可能要使用内置的filter()
。
欲了解更多详情, 请点击这里
#18楼
其他答案是正确的,因为从要迭代的列表中删除通常不是一个好主意。 反向迭代避免了陷阱,但是遵循这样做的代码要困难得多,因此通常最好使用列表推导或filter
。
但是,在一种情况下,可以安全地从要迭代的序列中删除元素:如果仅在迭代时删除一个项目。 这可以通过使用return
或break
来确保。 例如:
for i, item in enumerate(lst):
if item % 4 == 0:
foo(item)
del lst[i]
break
当您对满足条件的列表中的第一个项目执行副作用操作,然后立即从列表中删除该项目时,这通常比列表理解更容易理解。
#19楼
对于具有很大潜力的任何事物,我使用以下内容。
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)
那应该比其他任何东西都快得多。
#20楼
在某些情况下,您要做的不仅仅是一次过滤一个列表,还希望迭代时更改迭代。
这是一个示例,其中事先复制列表是不正确的,不可能进行反向迭代,并且列表理解也不是一种选择。
""" 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
#21楼
这里的大多数答案都希望您创建列表的副本。 我有一个用例,其中的列表很长(110K个项),而继续缩小列表会更明智。
首先,您需要将while循环替换为foreach循环 ,
i = 0
while i < len(somelist):
if determine(somelist[i]):
del somelist[i]
else:
i += 1
i
的值不会在if块中更改,因为一旦删除了旧项,您将希望从相同索引中获取新项的值。
#22楼
最有效的方法是列表理解,很多人都展示了他们的案例,当然,这也是通过filter
获得iterator
的好方法。
Filter
接收一个函数和一个序列。Filter
依次将传递的函数应用于每个元素,然后根据函数返回值是True
还是False
决定保留还是丢弃该元素。
有一个例子(在元组中获得赔率):
list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))
# result: [1, 5, 9, 15]
警告:您也不能处理迭代器。 迭代器有时比序列更好。
#23楼
我可以想到三种解决问题的方法。 例如,我将创建一个元组的随机列表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
的小代码删除满足上述条件的元组。 但是,如果两个连续放置的元组满足给定条件,则此方法将丢失一个元组(满足所述条件)。
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.>构造一个新列表,其中包含不满足给定条件的元素(元组)(这与删除满足给定条件的list的元素相同)。 以下是该代码:
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.>查找满足给定条件的索引,然后使用与这些索引相对应的remove元素(元组)。 以下是该代码。
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更有效。 我更喜欢method2 。 对于上述示例, time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7
#24楼
如果以后要使用新列表,则只需将elem设置为None,然后在以后的循环中对其进行判断,如下所示
for i in li:
i = None
for elem in li:
if elem is None:
continue
这样,您无需复制列表,而且更容易理解。
#25楼
for循环将通过索引进行迭代。
认为你有一个清单,
[5, 7, 13, 29, 65, 91]
您使用了名为lis
列表变量。 并且您使用它删除。
你的变量
lis = [5, 7, 13, 29, 35, 65, 91]
0 1 2 3 4 5 6
在第5次迭代中
您的数字35不是素数,因此您将其从列表中删除。
lis.remove(y)
然后下一个值(65)移至上一个索引。
lis = [5, 7, 13, 29, 65, 91]
0 1 2 3 4 5
所以第4次迭代完成的指针移到了第5位。
那就是为什么您的循环自从移入上一个索引以来不覆盖65。
因此,您不应将列表引用到另一个仍引用原始而不是副本的变量中。
ite = lis #dont do it will reference instead copy
所以使用list[::]
复制列表
现在你会给,
[5, 7, 13, 29]
问题是您在迭代过程中从列表中删除了一个值,然后列表索引将崩溃。
因此您可以尝试理解。
它支持所有可迭代的对象,例如list,tuple,dict,string等
#26楼
提出一个数字列表,您想删除所有可被3整除的数字,
list_number =[i for i in range(100)]
使用list comprehension
,这将创建一个新列表并创建新的内存空间
new_list =[i for i in list_number if i%3!=0]
使用lambda filter
功能,这将创建结果新列表并消耗内存空间
new_list = list(filter(lambda x:x%3!=0, list_number))
无需占用新列表和修改现有列表的存储空间
for index, value in enumerate(list_number):
if list_number[index]%3==0:
list_number.remove(value)
#27楼
如果要在迭代时从列表中删除元素,请使用while循环,以便可以在每次删除后更改当前索引和结束索引。
例:
i = 0
length = len(list1)
while i < length:
if condition:
list1.remove(list1[i])
i -= 1
length -= 1
i += 1
#28楼
嗨,我有以下问题:
我想遍历2个列表,如果两个列表中都包含obj,则将其删除。 最后,仍然应该有2个列表,这两个列表之间存在差异。
然后,我遇到了与此问题相同的索引问题。
我认为我找到了解决索引问题的不错的解决方案,并希望与您分享。
def get_diff(list1,list2):
index = 0
for obj in list1[index:]:
if obj in list2:
list1.remove(obj)
list2.remove(obj)
else:
index += 1
return list_rep_vols,list_aix_vols
我将索引定义为var,并告诉list1从索引开始迭代到list1的结尾。 因此,从技术上讲,我会告诉他,如果删除索引0,则索引1现在就是索引0。
这里是一个例子:
test = ["a", "z", "b", "f", "d"]
test1 = ["a", "b", "c", "e"]
test_re, test1_re = get_del_and_add_list_aix(test,test1)
print(test_re)
print(test1_re)
输出:
测试['z','f','d']
test1 ['c','e']
问候
克里斯拉玛
#29楼
我认为删除元素时使用while和un-increment是最简单的方法。
import random
def f(l, n):
# n shall not pass
idx = 0
while idx < len(l):
if l[idx] % 2 == n:
del l[idx]
continue
idx += 1
res = [random.randrange(1, 50) for i in range(10000)]
f(res, 0)
f(res, 1)
最后,res应该是[]。