How do I remove 'None' items from the end of a list in Python
Question:
A have a list that might contain items that are None. I would like to remove these items, but only if they appear at the end of the list, so:
[None, "Hello", None, "World", None, None]
# Would become:
[None, "Hello", None, "World"]
I have written a function, but I’m not sure this is the right way to go about it in python?:
def shrink(lst):
# Start from the end of the list.
i = len(lst) -1
while i >= 0:
if lst[i] is None:
# Remove the item if it is None.
lst.pop(i)
else:
# We want to preserve 'None' items in the middle of the list, so stop as soon as we hit something not None.
break
# Move through the list backwards.
i -= 1
Also a list comprehension as an alternative, but this seems inefficient and no more readable?:
myList = [x for index, x in enumerate(myList) if x is not None or myList[index +1:] != [None] * (len(myList[index +1:]))]
What it the pythonic way to remove items that are ‘None’ from the end of a list?
Answers:
Discarding from the end of a list is efficient.
while lst[-1] is None:
del lst[-1]
Add a safeguard for IndexError: pop from empty list
if necessary. It depends on your specific application whether proceeding with an empty list should be considered normal or an error condition.
while lst and lst[-1] is None:
del lst[-1]
Easiest way would probably be what you did. Here’s a conceptually simpler implementation of that:
def shrink(lst):
copy_lst = lst[:] # don't modify the original
while copy_lst[-1] is None: # you can get the last element in 1 step with index -1
copy_list.pop()
return copy_lst
As of python 3.8, and the walrus operator, it would be possible to do in a list comprehension, but this is a hacky solution and you shouldn’t use it:
def shrink(lst):
at_end = True
return reversed([(at_end := e is None and at_end, e)[1] for e in reversed(lst) if not at_end])
If you don’t want to modify the list, you can just find the first index from the right that isn’t None and slice to it:
def shrink(l):
for i in range(len(l) - 1, -1, -1):
if l[i] is not None:
return l[:i + 1]
return l[:0]
If you do want to modify the list in-place, you can just delete the slice:
def shrink(l):
for i in range(len(l) - 1, -1, -1):
if l[i] is not None:
break
else:
i = -1
del l[i + 1:]
A have a list that might contain items that are None. I would like to remove these items, but only if they appear at the end of the list, so:
[None, "Hello", None, "World", None, None]
# Would become:
[None, "Hello", None, "World"]
I have written a function, but I’m not sure this is the right way to go about it in python?:
def shrink(lst):
# Start from the end of the list.
i = len(lst) -1
while i >= 0:
if lst[i] is None:
# Remove the item if it is None.
lst.pop(i)
else:
# We want to preserve 'None' items in the middle of the list, so stop as soon as we hit something not None.
break
# Move through the list backwards.
i -= 1
Also a list comprehension as an alternative, but this seems inefficient and no more readable?:
myList = [x for index, x in enumerate(myList) if x is not None or myList[index +1:] != [None] * (len(myList[index +1:]))]
What it the pythonic way to remove items that are ‘None’ from the end of a list?
Discarding from the end of a list is efficient.
while lst[-1] is None:
del lst[-1]
Add a safeguard for IndexError: pop from empty list
if necessary. It depends on your specific application whether proceeding with an empty list should be considered normal or an error condition.
while lst and lst[-1] is None:
del lst[-1]
Easiest way would probably be what you did. Here’s a conceptually simpler implementation of that:
def shrink(lst):
copy_lst = lst[:] # don't modify the original
while copy_lst[-1] is None: # you can get the last element in 1 step with index -1
copy_list.pop()
return copy_lst
As of python 3.8, and the walrus operator, it would be possible to do in a list comprehension, but this is a hacky solution and you shouldn’t use it:
def shrink(lst):
at_end = True
return reversed([(at_end := e is None and at_end, e)[1] for e in reversed(lst) if not at_end])
If you don’t want to modify the list, you can just find the first index from the right that isn’t None and slice to it:
def shrink(l):
for i in range(len(l) - 1, -1, -1):
if l[i] is not None:
return l[:i + 1]
return l[:0]
If you do want to modify the list in-place, you can just delete the slice:
def shrink(l):
for i in range(len(l) - 1, -1, -1):
if l[i] is not None:
break
else:
i = -1
del l[i + 1:]