Have you tried using the reversed on the range?
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]
This way, when you delete an element, the array get reduced but since you are going through the list in a reversed order, only the index of already processed elements get affected.
EDIT
After reading all the comments, I decided to run some little benchmark. I created a list of 1,000 elements and a list of 10,000,000 elements and tried the 3 ways:
- #1 Deleting from list
- #2 Creating a new list with list comprehension
- #3 Creating a new list with classic for
For the list of 1,000 elements, the time does not really matter but for the 10,000,000 elements list, deleting from the list get pretty much impossible (a couple of hours vs half a second to create a new list).
Test with 1,000 element
>>> 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
Test with 10,000,000 element
>>> 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
In regards of this, I would strongly suggest creating a new list with the list comprehension or with a regular for loop.
Here is my code:
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')
test2 = [i for i in test1 if i % 2 != 0]?