Remove odd-indexed elements from list in Python

Question:

I’m trying to remove the odd-indexed elements from my list (where zero is considered even) but removing them this way won’t work because it throws off the index values.

lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']


def remove_odd_elements(lst):
    i=0
    for element in lst:
        if i % 2 == 0:
            pass
        else:
            lst.remove(element)
        i = i + 1

How can I iterate over my list and cleanly remove those odd-indexed elements?

Asked By: avereux

||

Answers:

You can delete all odd items in one go using a slice:

del lst[1::2]

Demo:

>>> lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
>>> del lst[1::2]
>>> lst
['712490959', '623726061', '552157404', '1285252944', '1130181076', '552157404', '545600725']

You cannot delete elements from a list while you iterate over it, because the list iterator doesn’t adjust as you delete items. See Loop "Forgets" to Remove Some Items what happens when you try.

An alternative would be to build a new list object to replace the old, using a list comprehension with enumerate() providing the indices:

lst = [v for i, v in enumerate(lst) if i % 2 == 0]

This keeps the even elements, rather than remove the odd elements.

Answered By: Martijn Pieters

Since you want to eliminate odd items and keep the even ones , you can use a filter as follows :

>>>filtered_lst=list(filter(lambda x : x % 2 ==0 , lst))

this approach has the overhead of creating a new list.

Answered By: jihed gasmi

It’s important to understand what is happening because modification during iteration is a common problem if it’s not done right

Here is a simple list

0, 1, 2, 3, 4, 5

When idx = 1, you drop element 1:

0, 2, 3, 4, 5
   ^

Then you increment idx two more times before dropping another element:

0, 2, 3, 4, 5
         ^

So now you have

0, 2, 3, 5

Luckily (or unluckily), a list iterator allows you to modify the underlying data without breaking.

There are a couple of ways to fix this. The first one is to iterate backwards. Also, don’t iterate over a collection when you modify it, keep the index external. You can still use a for loop though:

for idx in range(len(elements) - 1, -1, -1):
    if idx % 2:
        del elements[idx]

Don’t forget to use del to drop elements by index instead of value.

If you’re absolutely sure that the input has an even size, you can remove the conditional easily:

for idx in range(len(elements) - 1, -1, -2):
    del elements[idx]

For an arbitrary number of elements, it’s only slightly more complicated to avoid the last potentially even element:

for idx in range(len(elements) // 2 * 2 - 1, -1, -2):
    del elements[idx]

In python, there are short-hand indices you can use to drop the elements directly. To do it in-place:

del elements[1::2]

Or the more commonly suggested option of making a copy:

elements = elements[::2]
Answered By: Mad Physicist
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.