Як видалити елемент зі списку за індексом


1503

Як я можу видалити елемент із списку за індексом у Python?

Я знайшов list.removeметод, але скажіть, що хочу видалити останній елемент, як це зробити? Схоже, видалення за замовчуванням здійснює пошук у списку, але я не хочу, щоб якийсь пошук здійснювався.


10
@smci: Список Python заснований на масиві: щоб видалити елемент посередині, потрібно перемістити всі елементи праворуч, щоб усунути прогалину, тому він знаходиться O(n)в часі. deque()забезпечує ефективні операції з обох кінців, але не забезпечує вставки / огляди / видалення O (1) посередині.
jfs

@JFSebastian: Реалізація cPython, так, дякую, що мене виправили. Строго мовна специфікація не вказує, як реалізувати список, альтернативні реалізації можуть вибрати, як використовувати зв'язаний список.
smci

@smci: жодна практична реалізація Python не використовувала б O(n)індексний доступ a[i](через пов'язані списки). Примітка: реалізація на основі масиву забезпечує O(1)доступ до індексу.
jfs

@JFSebastian: звичайно. Я просто зазначив, що мовна специфіка цього не визначає , це питання впровадження. (Я був здивований, виявивши, що це не так.)
smci

@smci якщо ви орієнтуєтесь на це широко, я не впевнений, як ви можете сподіватися оптимізувати що-небудь.
Нік Т

Відповіді:


1740

Використовуйте delта вказуйте індекс елемента, який потрібно видалити:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Також підтримує фрагменти:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

Ось розділ із підручника.


53
Дякую, у чому різниця між поп та дель?
Джоан Венге

37
del перевантажений. Наприклад, del a видаляє весь список
Брайан Р. Бонді

34
інший приклад del a [2: 4], видаляє елементи 2 і 3
Брайан Р. Бонді

307
pop () повертає елемент, який потрібно видалити. del просто видаляє є.

13
Я не бачу доказів "пов'язаного списку" там. Подивіться на svn.python.org/projects/python/trunk/Objects/listobject.c, як PyList_GetItem()по суті повертається ((PyListObject *)op) -> ob_item[i];- ith елемент масиву.
glglgl

648

Ви, мабуть, хочете pop:

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

За замовчуванням popостанній елемент без жодних аргументів видаляє:

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

105
Не забувайте поп (-1). Так, це за замовчуванням, але я вважаю за краще, так що я не повинен пам'ятати, який кінець попсом використовується за замовчуванням.
S.Lott

282
Я не погоджуюсь. Якщо ви знаєте етимологію програмування програми "pop" (це операція, яка видаляє та повертає верхню частину структури даних "стека"), то вона pop()сама по собі є дуже очевидною, але pop(-1)потенційно заплутана саме тому, що вона надмірна.
coredumperror

a.pop (-1), щоб видалити останній?
zx1986

14
@ zx1986 a popв більшості мов програмування зазвичай видаляє останній елемент, як це робиться в Python. Отже, вказуєте ви -1 або нічого не відрізняється.
Паскаль

30
До речі, pop()повертає будь-який елемент, який він видалив.
Боб Штейн

136

Як і інші згадані поп і дель - це ефективні способи видалення елемента з даного індексу. І все-таки заради завершення (оскільки те саме можна зробити багатьма способами в Python):

Використання фрагментів (це не робить вилучення елемента з оригінального списку):

(Також це буде найменш ефективним методом при роботі зі списком Python, але це може бути корисно (але не ефективно, повторюю) під час роботи з визначеними користувачем об'єктами, які не підтримують pop, але все ж визначають a __getitem__):

>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index

>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]

Примітка. Зверніть увагу, що цей метод не змінює список на місцях, як popі del. Він замість цього робить дві копії списків (один від початку до індексу, але без нього ( a[:index]) і один після індексу до останнього елемента ( a[index+1:])) та створює новий об'єкт списку, додаючи обидва. Потім це переназначається на змінну списку ( a). Отже, старий об'єкт списку відміняється і, відповідно, збирається сміття (за умови, що на оригінальний об'єкт списку не посилається жодна змінна, крім a).

Це робить цей метод дуже неефективним і він також може спричинити небажані побічні ефекти (особливо, коли інші змінні вказують на оригінальний об'єкт списку, який залишається незмінним).

Дякуємо @MarkDickinson за вказівку на це ...

Ця відповідь переповнення стека пояснює поняття нарізки.

Також зауважте, що це працює лише з позитивними показниками.

Під час використання з об'єктами __getitem__метод повинен бути визначений, а ще важливіше, що __add__метод повинен був бути визначений для повернення об'єкта, що містить елементи з обох операндів.

По суті, це працює з будь-яким об’єктом, визначення класу якого:

class foo(object):
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return foo(self.items[index])

    def __add__(self, right):
        return foo( self.items + right.items )

Це працює, за допомогою listякого визначаються __getitem__та __add__методи.

Порівняння трьох способів з точки зору ефективності:

Припустимо, що заздалегідь визначено:

a = range(10)
index = 3

del object[index]метод:

На сьогоднішній день найбільш ефективний метод. Це працює, всі об'єкти, які визначають __del__метод.

Розбирання здійснюється наступним чином:

Код:

def del_method():
    global a
    global index
    del a[index]

Розбирання:

 10    0 LOAD_GLOBAL     0 (a)
       3 LOAD_GLOBAL     1 (index)
       6 DELETE_SUBSCR   # This is the line that deletes the item
       7 LOAD_CONST      0 (None)
      10 RETURN_VALUE
None

pop метод:

Він менш ефективний, ніж метод del, і застосовується, коли вам потрібно отримати видалений елемент.

Код:

def pop_method():
    global a
    global index
    a.pop(index)

Розбирання:

 17     0 LOAD_GLOBAL     0 (a)
        3 LOAD_ATTR       1 (pop)
        6 LOAD_GLOBAL     2 (index)
        9 CALL_FUNCTION   1
       12 POP_TOP
       13 LOAD_CONST      0 (None)
       16 RETURN_VALUE

Метод зрізу та додавання.

Найменш ефективний.

Код:

def slice_method():
    global a
    global index
    a = a[:index] + a[index+1:]

Розбирання:

 24     0 LOAD_GLOBAL    0 (a)
        3 LOAD_GLOBAL    1 (index)
        6 SLICE+2
        7 LOAD_GLOBAL    0 (a)
       10 LOAD_GLOBAL    1 (index)
       13 LOAD_CONST     1 (1)
       16 BINARY_ADD
       17 SLICE+1
       18 BINARY_ADD
       19 STORE_GLOBAL   0 (a)
       22 LOAD_CONST     0 (None)
       25 RETURN_VALUE
None

Примітка. У всіх трьох розбираннях ігноруються останні два рядки, які в основному є return None. Також перші два рядки завантажують глобальні значення aі index.


4
Ваш метод нарізки не видаляє елемент зі списку: натомість він створює новий об’єкт списку, що містить усі, крім i-го запису, з початкового списку. Оригінальний список не змінюється.
Марк Дікінсон

@MarkDickinson Відредагували відповідь, щоб уточнити те саме ... Будь ласка, дайте мені знати, чи виглядає вона зараз добре?
Рагав Р.В.

6
Можливо, відповідь була не повністю на тему, але метод індексації корисний, якщо вам потрібно опустити елемент із незмінного об'єкта, наприклад кортежу. в цьому випадку pop () і del () не працюватимуть.
Калеб

6
@ rvraghav93 з усіх представлених методів протягом усього поста, a = a[:index] + a[index+1 :]-трик був найбезпечнішим, коли мова йде про величезні списки. Усі інші методи опинилися в глухому куті. Тож велике вам дякую
user3085931

3
Дійсно Марк, ти бурхливий. Цю відповідь я віддав перевагу тому, що вона була справді педагогічною. Я найбільше дізнався з цієї відповіді та деталей демонтажу, які були надані, та впливу на виконання. Плюс метод нарізки, так, створіть інший об’єкт, але зараз він вказаний, а іноді це теж те, що вам потрібно.
Йохан Обадія

52

popтакож корисно для видалення та збереження елемента зі списку. Де delнасправді випадає предмет.

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2

24

Якщо ви хочете видалити певний елемент позиції зі списку, наприклад 2-го, 3-го та 7-го. ви не можете використовувати

del my_list[2]
del my_list[3]
del my_list[7]

Оскільки після видалення другого елемента, третій елемент, який ви видаляєте, фактично є четвертим елементом у вихідному списку. Ви можете відфільтрувати 2-й, 3-й та 7-й елементи в оригінальному списку та отримати новий список, як нижче:

new list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

19

Це залежить від того, що ви хочете зробити.

Якщо ви хочете повернути видалений елемент, скористайтеся pop():

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

Однак якщо ви просто хочете видалити елемент, використовуйте del:

>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]

Крім того, delдозволяє використовувати скибочки (наприклад del[2:]).


18

Як правило, я використовую такий метод:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]

15

Ще один спосіб видалення елементів (-ів) зі списку за індексом.

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a [x: y] вказує на елементи від індексу xдо y-1. Коли ми оголошуємо цю частину списку порожнім списком ( []), ці елементи видаляються.


14

Ви можете просто шукати елемент, який потрібно видалити. Це дійсно просто. Приклад:

    letters = ["a", "b", "c", "d", "e"]
    letters.remove(letters[1])
    print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)

Вихід: акде


6
Мені подобається це рішення, але, звичайно, він передбачає, що у вашому списку немає дублікатів.
tommy.carstensen

11

Щоб видалити елемент зі списку, використовуйте наступний код:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

Якщо ви хочете видалити дані елемента індексу зі списку, використовуйте:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

2
Посилається на застереження, що ваш список не може містити дублікатів.
tommy.carstensen

3
Це не видалення за індексом, а вилучення за відповідним значенням. Це може бути цінною інформацією для деяких людей, які відвідують тут, але взагалі не намагаються відповісти на питання ОП.
Антон

8

Як було сказано раніше, найкраща практика - del (); або pop (), якщо вам потрібно знати значення.

Альтернативним рішенням є повторна складання лише тих елементів, які ви хочете:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

eta: hmm ... не працюватиме на негативних значеннях індексу, буде розмірковувати та оновлюватись

Я вважаю

if index_<0:index_=len(list_)+index_

підклеїть його ... але раптом ця ідея здається дуже крихкою. Хоча цікавий продуманий експеримент. Здається, має бути "правильний" спосіб зробити це з допомогою розуміння додавання () / списку.

розмірковування


1
Яка версія Python має функцію del()? Для цієї функції ви надаєте список як перший аргумент цієї функції, а потім індекс, або індекс спочатку, а потім список? Чи повертає аргумент списку без елемента, чи робить це видалення на місці. Я знаю про delтвердження, але не про функцію з такою ж назвою.
Антон

8

Це не здається, що ви працюєте зі списком списків, тому я триматиму це коротко. Ви хочете використовувати pop, оскільки він буде видаляти елементи, а не елементи, які є списками, для цього слід використовувати del. Для виклику останнього елемента в python це "-1"

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

1
pop()і delобидва видаляють елемент із заданого індексу, незалежно від того, є сам цей список списком чи ні. a = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b
Антон

8

l - список значень; ми повинні видалити індекси зі списку inds2rem .

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

не працює, відповідь така <map at 0x7f4d54109a58>. і l - діапазон (0,20)
Хітеш

7

Використовуйте функцію "del" :

del listName[-N]

Наприклад, якщо ви хочете видалити останні три елементи, ваш код повинен бути:

del listName[-3:]

Наприклад, якщо ви хочете видалити останні 8 елементів, ваш код повинен бути:

del listName[-8:]

2
delє заявою . Якби це була функція, вам доведеться написатиdel(listame[-N])
Антон

7

Вже згадувалося, як видалити один елемент із списку та які переваги мають різні методи. Однак зауважте, що видалення декількох елементів має певний потенціал помилок:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

Елементи 3 та 8 (не 3 та 7) з початкового списку були видалені (оскільки список був скорочений під час циклу), що, можливо, не було наміром. Якщо ви хочете безпечно видалити декілька індексів, слід замість цього спочатку видалити елементи з найвищим індексом, наприклад, наприклад:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]

4

Або якщо потрібно видалити кілька індексів:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

Звичайно, тоді також можна було б зробити:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

1
Чому ви просто не сортуєте список індексів у зворотному порядку і не видаляєте їх по черзі? Таким чином, вам не доведеться складати новий список.
Антон

3

Ви можете використовувати або del, або pop, щоб видалити елемент зі списку на основі індексу. Pop надрукує член, який він видаляє зі списку, а список видалить його, не надрукувавши його.

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

3

Можна використовувати del або pop, але я віддаю перевагу del, оскільки ви можете вказати індекс та фрагменти, що надає користувачеві більше контролю над даними.

Наприклад, починаючи зі показаного списку, можна видалити останній елемент у delвигляді фрагмента, а потім можна видалити останній елемент із результату, використовуючи pop.

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.