Как удалить элементы "Нет" из конца списка в Python

Есть список, который может содержать элементы, которых нет. Я хотел бы удалить эти элементы, но только если они появляются в конце списка, поэтому:

[None, "Hello", None, "World", None, None]
# Would become:
[None, "Hello", None, "World"]

Я написал функцию, но я не уверен, что это правильный путь в 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

Также в качестве альтернативы можно использовать понимание списка, но это кажется неэффективным и не более читабельным?:

myList = [x for index, x in enumerate(myList) if x is not None or myList[index +1:] != [None] * (len(myList[index +1:]))]

Какой это питонский способ удалить элементы, которые "Нет", из конца списка?

Ответы

Ответ 1

Сброс с конца списка эффективен.

while lst[-1] is None:
    del lst[-1]

При необходимости добавьте защиту для IndexError: pop from empty list. От вашего конкретного приложения зависит, следует ли считать обработку пустого списка нормальной или ошибочной.

while lst and lst[-1] is None:
    del lst[-1]

Ответ 2

Если вы не хотите изменять список, вы можете просто найти первый индекс справа, который не является None, и нарезать его:

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]

Если вы хотите изменить список на месте, вы можете просто удалить срез:

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:]

Ответ 3

Самый простой способ - это то, что ты сделал. Вот концептуально более простая реализация этого:

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

Начиная с python 3.8 и оператора моржа, это можно было бы сделать с помощью понимания списка, но это хакерское решение, и вы не должны его использовать:

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])