问题:
test1 = [1, 2, 3]
for i in range(len(test1)): #Want to do the below for every element in test1
print(test1[i])
if test1[i] % 2 == 0: #if the element meets certain conditions, it gets deleted
del test1[i]
#The thing in test1 gets deleted, but the range gets not updated,
#and i iterates nonetheless, so 1 element gets ignored,
#and in the end, I get "list index out of range"
(在实际的代码中,if语句要多得多,并且数组中的东西不是整数而是类的对象?!所以列表理解更多 - meh ......)
我提出了这种方法:
test1 = [1, 2, 3]
i = 0
x = len(test1)
while i < x:
print(test1[i])
if test1[i] % 2 == 0:
del test1[i]
x -= 1
i -= 1
i += 1
但正如你所看到的,这是5行(对于每个del,我必须添加2行......),丑陋和烦人。有没有更好的办法做这样的事情?比如,直接进入for循环的重做命令会更新范围,让你选择i或其他东西吗?
答案 0 :(得分:6)
使用列表理解
有些事情:
list = [x for x in list if x % 2 == 1] # Keep anything that is not even
for thing in list:
print(thing)
这将创建一个包含与条件匹配的任何内容的新列表。 然后打印新列表
>>> test1 = [1,2,3]
>>> list = [x for x in test1 if x % 2 is 1]
>>> print(list)
[1, 3]
答案 1 :(得分:3)
您是否尝试过使用范围内的reversed
?
test1 = [1, 2, 3]
for i in reversed(range(len(test1))):
print(test1[i])
if test1[i] % 2 == 0:
del test1[i]
>>> 3
>>> 2
>>> 1
print(test1)
>>> [1, 3]
这样,当你删除一个元素时,数组会减少,但由于你以相反的顺序浏览列表,所以只有已处理元素的索引才会受到影响。
阅读完所有评论后,我决定运行一些小基准测试。我创建了一个包含1,000个元素的列表和10,000,000个元素的列表,并试用了3种方法:
对于1,000个元素的列表,时间并不重要,但对于10,000,000个元素列表,从列表中删除几乎是不可能的(创建一个新列表需要几个小时vs半秒)。
使用1,000个元素进行测试
>>> Test 0, 11th element: 7e-06 seconds
>>> Test 0, second last element: 2e-06 seconds
>>> Test 1: 0.00017 seconds
>>> Test 2: 0.000103 seconds
>>> Test 3: 0.000234 seconds
使用10,000,000元素进行测试
>>> Test 0, 11th element: 0.011888 seconds
>>> Test 0, second last element: 4e-06 seconds
>>> Test 1: Too long!!
>>> Test 2: 0.941158 seconds
>>> Test 3: 0.681262 seconds
关于这一点,我强烈建议使用列表推导或定期for循环创建一个新列表。
这是我的代码:
from datetime import datetime
from random import randint
# Create my test lists of 10 000 000 elements
test_0 = []
#nb_el = 10000000
nb_el = 1000
while (len(test_0) < nb_el):
test_0.append(randint(0, 100))
test_1 = test_0[:] # clone list1
test_2 = test_0[:] # clone list1
test_3 = test_0[:] # clone list1
# Test #0
# Remove the 11th element and second last element
d1 = datetime.now()
del test_0[10]
d2 = datetime.now()
print('Test 0, 11th element: ' +
str((d2-d1).microseconds / 1000000.0) + ' seconds')
d1 = datetime.now()
del test_0[nb_el-2]
d2 = datetime.now()
print('Test 0, second last element: '
+ str((d2-d1).microseconds / 1000000.0) + ' seconds')
# Test #1 | TOO SLOW TO BE RAN with 10 000 000 elements
# Delete every element where element is a multiple of 2
d1 = datetime.now()
for i in reversed(range(len(test_1))):
if test_1[i] % 2 == 0:
del test_1[i]
d2 = datetime.now()
print('Test 1: ' + str((d2-d1).microseconds / 1000000.0) + ' seconds')
# Test #2
# Create a new list with every element multiple of 2
# using list comprehension
d1 = datetime.now()
test_2_new = [x for x in test_2 if x % 2 == 0]
d2 = datetime.now()
print('Test 2: ' + str((d2-d1).microseconds / 1000000.0) + ' seconds')
# Test #3
# Create a new list with every element multiple of 2
# using for loop
d1 = datetime.now()
test_3_new = []
for i in range(len(test_3)):
if test_3[i] % 2 == 0:
test_3_new.append(test_3[i])
d2 = datetime.now()
print('Test 3: ' + str((d2-d1).microseconds / 1000000.0) + ' seconds')
答案 2 :(得分:3)
假设您想要从列表中删除它们之前打印每个数字。
myList = [1,2,3]
for n in test1:
print n
test1 = [n for n in myList if n % 2] # 0 = False by default in python. No need for == 0 / > 0.
如果您绝对想要使用您编写的代码,因为您可能更容易理解:
test1 = [1, 2, 3]
for i in range(len(test1)): #Want to do the below for every element in test1
print(test1[i])
# Either check if the index is not greather than the length of the list.
if test1[i] % 2 == 0 and i <= len(test1): #if the element meets certain conditions, it gets deleted
# Or use try, except (Will be slow if your list is great in size as there will be many exceptions caught.
if test1[i] % 2 == 0:
try:
del test1[i]
except:
continue
#The thing in test1 gets deleted, but the range gets not updated,
#and i iterates nonetheless, so 1 element gets ignored,
#and in the end, I get "list index out of range"
答案 3 :(得分:1)
在您迭代迭代时修改迭代可能会给您带来很多麻烦。请尝试以下方法:
test1 = [1,2,3]
test2 = []
for i in test1:
print(i)
if i%2:
test2.append(i)
然后你有test2
作为完成版本。
这可以通过理解更紧凑地编写:
test1 = [1,2,3]
test2 = [i for i in test1 if i%2]
print(*test2, sep='\n')