Document directory
-
- Traverse and delete elements from the forward
-
- Use List resolution (list comprehension)
-
- Use filter
-
- Use the itertools Module
- Manual loop and remove
- Performance
- Reference
When we want to delete elements while traversing a list, we may encounter some problems. First, let's look at the following code:
my_list = [1, 2, 4, 5]for elem in my_list: if elem % 2 == 0: my_list.remove(elem)print my_list
We certainly want the output of this code to be [1, 5], but in fact it is [1, 4, 5]. The possible cause is that when my_list is traversed, an index is stored inside the ITER created by the for loop. When 2 is traversed, Index = 1. When 2 is deleted, the next index is 2, and my_list has only three elements [1, 4, 5]. In this case, my_list [2] = 5, so 5% 2! = 0. The element 4 is skipped. We can solve this problem using the following methods.
Traverse and delete elements from the forwardmy_list = [1, 2, 4, 5]for i in range(len(my_list) - 1, -1, -1): if my_list[i] % 2 == 0: my_list.remove(my_list[i])print my_list
Here we traverse the entire list from the back to the front and use the subscript.
Use List resolution (list comprehension) my_list = [1, 2, 4, 5] print [elem for elem in my_list if elem % 2 != 0]
The list parsing code is very simple. The difference here is that we have created a new list, which is usually a common method in Python.
Use filterprint filter(lambda x: x % 2, [1, 2, 4, 5])
Using filter is similar to using list resolution. It also creates a new list and completes the task in one row.
Use the itertools Module import itertools print [elem for elem in itertools.ifilter(lambda x: x%2, [1, 2, 4, 5])] print [elem for elem in itertools.ifilterfalse(lambda x: x%2 == 0, [1, 2, 4, 5])]
Ifilter * returns a generator used to iterate the entire list
Manual loop and removemy_list = [1, 2, 4, 5]# in place removedest = 0for i in range(len(my_list)): if my_list[i] % 2 != 0: if my_list[i] != my_list[dest]: my_list[dest] = my_list[i] dest += 1# all elements in [0, dest) is odd# so we remove all the elements in [dest, len(my_list))del my_list[dest:len(my_list)]print my_list
PerformanceThe efficiency of different methods is different. Let's perform a simple test to delete an even number from a randomly generated list with 10000 elements, and perform an iteration for 100 times to test the performance of different methods.
Cpython 2.6.4, Windows 7, CPU phenom II 945, and memory 4G are used for testing.
Method |
Time (s) |
Traverse and delete elements from the forward |
6.537 |
Use List resolution (list comprehension) |
0.205 |
Use filter |
0.203 |
Use the itertools Module |
0.210 |
Manual loop and remove |
0.227 |
We can see that the performance of the itertools method is much higher than that of the forward Traversal method by using list resolution and filter. The efficiency of manual loop and remove is not as high as imagined. You can see that using existing functions can easily achieve high efficiency.
Reference
Http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python