Разница между del, remove и pop в списках

>>> a=[1,2,3]
>>> a.remove(2)
>>> a
[1, 3]
>>> a=[1,2,3]
>>> del a[1]
>>> a
[1, 3]
>>> a= [1,2,3]
>>> a.pop(1)
2
>>> a
[1, 3]
>>> 

Есть ли разница между тремя вышеупомянутыми способами удаления элемента из списка?

15 ответов

Решение

Да, remove удаляет первое совпадающее значение, а не конкретный индекс:

>>> a = [0, 2, 3, 2]
>>> a.remove(2)
>>> a
[0, 3, 2]

del удаляет элемент по определенному индексу:

>>> a = [3, 2, 2, 1]
>>> del a[1]
>>> a
[3, 2, 1]

а также pop удаляет элемент по определенному индексу и возвращает его.

>>> a = [4, 3, 5]
>>> a.pop(1)
3
>>> a
[4, 5]

Их режимы ошибок тоже разные:

>>> a = [4, 5, 6]
>>> a.remove(7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> del a[7]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a.pop(7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop index out of range

Использование del удалить элемент по индексу, pop() удалить его по индексу, если вам нужно возвращаемое значение, и remove() удалить элемент по значению. Последний требует поиска в списке и поднимает ValueError если в списке нет такого значения.

При удалении индекса i из списка n элементы, вычислительные сложности этих методов

del     O(n - i)
pop     O(n - i)
remove  O(n)

Так как никто другой не упомянул об этом, обратите внимание, что del (В отличие от pop) позволяет удалить диапазон индексов из-за нарезки списка:

>>> lst = [3, 2, 2, 1]
>>> del lst[1:]
>>> lst
[3]

Это также позволяет избежать IndexError если индекс отсутствует в списке:

>>> lst = [3, 2, 2, 1]
>>> del lst[10:]
>>> lst
[3, 2, 2, 1]

Уже неплохо ответили другие. Это с моего конца:)

удалить против поп против дель

Очевидно, pop единственный, который возвращает значение, и remove является единственным, который ищет объект, в то время как del ограничивается простым удалением.

Здесь много лучших объяснений, но я постараюсь сделать все возможное, чтобы упростить еще.

Среди всех этих методов reverse & pop - это постфикс, а delete - префикс.

remove (): используется для удаления первого вхождения элемента

remove(i) => первое вхождение значения i

>>> a = [0, 2, 3, 2, 1, 4, 6, 5, 7]
>>> a.remove(2)   # where i = 2
>>> a
[0, 3, 2, 1, 4, 6, 5, 7]

pop(): используется для удаления элемента, если:

неопределенные

pop() => от конца списка

>>>a.pop()
>>>a
[0, 3, 2, 1, 4, 6, 5]

указанный

pop(index) => индекса

>>>a.pop(2)
>>>a
[0, 3, 1, 4, 6, 5]

ВНИМАНИЕ: впереди опасный метод

delete (): это префиксный метод.

Следите за двумя различными синтаксисами для одного и того же метода: [] и (). Он обладает способностью:

1. Удалить индекс

del a[index] => используется для удаления индекса и связанного с ним значения так же, как pop.

>>>del a[1]
>>>a
[0, 1, 4, 6, 5]

2. Удалить значения в диапазоне [индекс 1: индекс N]

del a[0:3] => несколько значений в диапазоне

>>>del a[0:3]
>>>a
[6, 5]

3.Последний, но не список, чтобы удалить весь список за один раз

del (a) => как сказано выше.

>>>del (a)
>>>a

Надеюсь, что это проясняет путаницу, если таковые имеются.

pop - принимает индекс и возвращает значение

удалить - принимает значение, удаляет первое вхождение и ничего не возвращает

delete - принимает индекс, удаляет значение по этому индексу и ничего не возвращает

Любая операция / функция в различных структурах данных определяется для конкретных действий. Вот в вашем случае т.е. удаление элемента, удаление, выскочить и удалить. (Если вы рассматриваете наборы, добавьте еще одну операцию - отбросьте) Другой запутанный случай - при добавлении. Включить /Append. Для демонстрации, давайте введем deque. deque - это гибридная линейная структура данных, в которую можно добавлять элементы / удалять элементы с обоих концов (задний и передний концы).

class Deque(object):

  def __init__(self):

    self.items=[]

  def addFront(self,item):

    return self.items.insert(0,item)
  def addRear(self,item):

    return self.items.append(item)
  def deleteFront(self):

    return self.items.pop(0)
  def deleteRear(self):
    return self.items.pop()
  def returnAll(self):

    return self.items[:]

Здесь, см. Операции:

def deleteFront(self):

    return self.items.pop(0)
def deleteRear(self):
    return self.items.pop()

Шеф должен что-то вернуть. Итак, поп - с индексом и без. Если я не хочу возвращать значение: del self.items[0]

Удалить по значению, а не по индексу:

  • Удалить:

    list_ez=[1,2,3,4,5,6,7,8]
    for i in list_ez:
        if i%2==0:
            list_ez.remove(i)
    print list_ez
    

Возвращает [1,3,5,7]

рассмотрим случай множеств.

set_ez=set_ez=set(range(10))

set_ez.remove(11)

# Gives Key Value Error. 
##KeyError: 11

set_ez.discard(11)

# Does Not return any errors.

Вот подробный ответ.

del может использоваться для любого объекта класса, тогда как pop и remove и привязаны к определенным классам.

За del

вот несколько примеров

>>> a = 5
>>> b = "this is string"
>>> c = 1.432
>>> d = myClass()

>>> del c
>>> del a, b, d   # we can use comma separated objects

Мы можем преодолеть __del__ в пользовательских классах.

Конкретное использование со списком

>>> a = [1, 4, 2, 4, 12, 3, 0]
>>> del a[4]
>>> a
[1, 4, 2, 4, 3, 0]

>>> del a[1: 3]   # we can also use slicing for deleting range of indices
>>> a
[1, 4, 3, 0]

За pop

pop принимает индекс как параметр и удаляет элемент по этому индексу

в отличие del, pop при вызове объекта списка возвращает значение по этому индексу

>>> a = [1, 5, 3, 4, 7, 8]
>>> a.pop(3)  # Will return the value at index 3
4
>>> a
[1, 5, 3, 7, 8]

За remove

remove принимает значение параметра и удаляет это значение из списка.

Если присутствует несколько значений, будет удалено первое вхождение

Note: Выбросит ValueError, если это значение отсутствует

>>> a = [1, 5, 3, 4, 2, 7, 5]
>>> a.remove(5)  # removes first occurence of 5
>>> a
[1, 3, 4, 2, 7, 5]
>>> a.remove(5)
>>> a
[1, 3, 4, 2, 7]

Надеюсь, этот ответ будет вам полезен.

Удалить в основном работает над значением. Удалить и открыть работу по индексу

Удалить в основном удаляет первое совпадающее значение. Delete удаляет элемент из определенного индекса. Pop в основном принимает индекс и возвращает значение по этому индексу. В следующий раз, когда вы распечатаете список, значение не появится.

Операция удаления в списке получает значение для удаления. Он ищет в списке, чтобы найти элемент с этим значением, и удаляет первый соответствующий элемент, который он находит. Это ошибка, если нет соответствующего элемента, вызывает ValueError.

>>> x = [1, 0, 0, 0, 3, 4, 5]
>>> x.remove(4)
>>> x
[1, 0, 0, 0, 3, 5]
>>> del x[7]
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    del x[7]
IndexError: list assignment index out of range

Оператор del может использоваться для удаления всего списка. Если у вас есть определенный элемент списка в качестве аргумента для del (например, listname[7] для конкретной ссылки на восьмой элемент в списке), он просто удалит этот элемент. Можно даже удалить "ломтик" из списка. Это ошибка, если индекс выходит за пределы диапазона, вызывает ошибку IndexError.

>>> x = [1, 2, 3, 4]
>>> del x[3]
>>> x
[1, 2, 3]
>>> del x[4]
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    del x[4]
IndexError: list assignment index out of range

Обычное использование pop - удалить последний элемент из списка, когда вы используете список в качестве стека. В отличие от del, pop возвращает значение, которое он вытолкнул из списка. При желании вы можете задать индексное значение для pop и pop, отличное от конца списка (например, listname.pop(0) удалит первый элемент из списка и вернет этот первый элемент в качестве результата). Вы можете использовать это, чтобы список вел себя как очередь, но есть доступные библиотечные подпрограммы, которые могут обеспечить работу очереди с большей производительностью, чем pop (0). Это ошибка, если индекс выходит за пределы диапазона, вызывает ошибку IndexError.

>>> x = [1, 2, 3] 
>>> x.pop(2) 
3 
>>> x 
[1, 2]
>>> x.pop(4)
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    x.pop(4)
IndexError: pop index out of range

См. Collection.deque для более подробной информации.

В то время как pop и delete оба принимают индексы для удаления элемента, как указано в комментариях выше. Ключевым отличием является сложность времени для них. Временная сложность для pop() без индекса равна O(1), но это не тот же случай для удаления последнего элемента.

Если ваш вариант использования всегда заключается в удалении последнего элемента, всегда предпочтительно использовать pop(), а не delete(). Для получения дополнительной информации о временных сложностях вы можете обратиться к https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt

Есть ли разница между этими тремя методами?

Варианты использования разные. Вот несколько примеров.

  • Поскольку возвращает удаленный элемент, это полезно, если возвращаемое значение важно. Например, его можно использовать для «разделения» списка на две части, используя список индексов списка (что-то вроде установленной разницы). Однако, посколькуpop()меняет список, убедитесь, что список индексов отсортирован в порядке убывания (чтобы удаление элементов сзади не влияло на индекс элементов спереди). Пример:

            lst = [1, 1, 2, 30, 40, 3, 2]
    new_lst_idx = [4, 3, 0]             # sorted in descending order
    
    new_lst = [lst.pop(i) for i in new_lst_idx]  # [40, 30, 1]
    lst                                          # [1, 2, 3, 2]
    
  • delудаляет ссылки на объекты Python, поэтому, как упоминалось в других ответах, часть списка можно удалить за один раз, что намного быстрее, чем удаление элементов один за другим. Фактически, если мы выполним тест timeit, удаление среза займет то же время, что и удаление элемента.

            import timeit
    setup = """
    def del_slice(lst):
        del lst[-100:]
    
    def del_item(lst):
        del lst[-100]
    
    lst = list(range(10000))
    """
    t1 = min(timeit.repeat("del_slice(lst.copy())", setup, number=1000)) # 0.043364200013456866
    t2 = min(timeit.repeat("del_item(lst.copy())", setup, number=1000))  # 0.04249859999981709
    
  • remove()удаляет элемент по значению, поэтому его можно использовать для фильтрации значений, но он настолько медленный, что, вероятно, в любом случае лучше использовать альтернативные методы, такие как понимание списка.

    Как следует из ответа Свена Марнаха , если вы удалите элементы из начала списка, все три будут работать одинаково (опять же, если это требуется часто, тогдаcollections.dequeвероятно, лучшая структура данных). Ниже показано, что фактически нет разницы между этими тремя методами, если первый элемент удален из списка.

            setup = "lst = list(range(10000))"
    t1 = min(timeit.repeat("lst.pop(0)", setup, number=10000))          # 0.019651099981274456
    t2 = min(timeit.repeat("del lst[0]", setup, number=10000))          # 0.015160200011450797
    t3 = min(timeit.repeat("lst.remove(lst[0])", setup, number=10000))  # 0.01593300001695752
    

Разница между del, pop и remove с точки зрения скорости выполнения:

При удалении любого промежуточного элемента:

      import timeit
print(timeit.timeit("a=[1,2,3,4,5]\ndel a[3]",number=100000))
print(timeit.timeit("a=[1,2,3,4,5]\na.pop(3)",number=100000))
print(timeit.timeit("a=[1,2,3,4,5]\na.remove(3)",number=100000))

против против :

      0.019387657986953855
0.02506213402375579
0.033232167130336165

del() кажется значительно быстрее двух других, а remove() — самым медленным.

При удалении последнего элемента:

      print(timeit.timeit("a=[1,2,3,4,5]\ndel a[-1]",number=100000))
print(timeit.timeit("a=[1,2,3,4,5]\na.pop()",number=100000))
print(timeit.timeit("a=[1,2,3,4,5]\na.remove(5)",number=100000))

delпротивpopпротивremove:

      0.01974551402963698
0.020333584863692522
0.03434014297090471

del() и pop() занимают одинаковое время, удаляя последний элемент.

remove(), del и pop() работают медленно... А как насчет «Нет»?

Среди стольких ответов я не видел, чтобы кто-нибудь говорил о производительности. Итак, у меня есть совет по производительности:

remove(), del и pop() после удаления перемещают все оставшиеся значения влево...

      1, 2, 3, 4, 5, 6
remove(3)
1, 2, <- 4, 5, 6

... замедляет обработку!

Изменение желаемого значения на ноль для дальнейшей обработки только удалений может значительно увеличить скорость вашей программы, особенно при работе с большим объемом данных:

      my_array[2] = None

Конечно, установка нулевого значения отличается от его удаления, но если вы хотите немного больше понять об удалении, размышления о производительности этой операции мне тоже кажутся интересными.

Вы также можете использовать команду remove для удаления значения по индексу.

n = [1, 3, 5]

n.remove(n[1])

Тогда n будет ссылаться на [1, 5]

Другие вопросы по тегам