Cách xóa phần tử khỏi danh sách theo chỉ mục


1506

Làm cách nào để xóa phần tử khỏi danh sách theo chỉ mục trong Python?

Tôi đã tìm thấy list.removephương thức, nhưng nói rằng tôi muốn loại bỏ phần tử cuối cùng, làm thế nào để tôi làm điều này? Có vẻ như mặc định xóa tìm kiếm danh sách, nhưng tôi không muốn bất kỳ tìm kiếm nào được thực hiện.


10
@smci: Danh sách Python dựa trên mảng: để xóa một mục ở giữa, bạn phải di chuyển tất cả các mục ở bên phải để xóa khoảng cách đó là lý do tại sao nó đang O(n)hoạt động. deque()cung cấp các hoạt động hiệu quả ở cả hai đầu nhưng nó không cung cấp các phần chèn / tra cứu / xóa O (1) ở giữa.
jfs

@JFSebastian: triển khai cPython, vâng, cảm ơn vì đã sửa lỗi cho tôi. Nghiêm khắc thông số ngôn ngữ không chỉ định cách triển khai danh sách, việc triển khai thay thế có thể chọn sử dụng danh sách được liên kết.
smci

@smci: không có triển khai Python thực tế nào sẽ sử dụng O(n)truy cập chỉ mục a[i](do danh sách được liên kết). Lưu ý: thực hiện dựa trên mảng cung cấp O(1)truy cập chỉ mục.
jfs

@JFSebastian: tất nhiên. Tôi chỉ lưu ý rằng thông số ngôn ngữ không xác định điều này , đó là một vấn đề triển khai. (Tôi đã rất ngạc nhiên khi thấy rằng nó đã không xảy ra.)
smci

@smci nếu bạn nhắm mục tiêu rộng rãi, tôi không chắc bạn có thể hy vọng tối ưu hóa mọi thứ như thế nào.
Nick T

Câu trả lời:


1740

Sử dụng delvà chỉ định chỉ mục của phần tử bạn muốn xóa:

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

Cũng hỗ trợ lát:

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

Đây là phần từ hướng dẫn.


53
Cảm ơn, sự khác biệt giữa pop và del là gì?
Joan Venge

37
del bị quá tải. Ví dụ: del a xóa toàn bộ danh sách
Brian R. Bondy

34
một ví dụ khác del a [2: 4], xóa các phần tử 2 và 3
Brian R. Bondy

307
pop () trả về phần tử bạn muốn loại bỏ. del chỉ xóa là được.

13
Tôi không thể thấy một bằng chứng về "danh sách liên kết" ở đó. Hãy xem svn.python.org/projects/python/trunk/Objects/listobject.c về PyList_GetItem()cơ bản trả về ((PyListObject *)op) -> ob_item[i];- iphần tử thứ của một mảng.
glglgl

649

Bạn có thể muốn pop:

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

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

Theo mặc định, popkhông có bất kỳ đối số nào sẽ xóa mục cuối cùng:

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

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

105
Đừng quên pop (-1). Vâng, đó là mặc định, nhưng tôi thích nó hơn vì vậy tôi không cần phải nhớ kết thúc sử dụng pop nào theo mặc định.
S.Lott

282
Tôi không đồng ý. Nếu bạn biết từ nguyên của lập trình viên "pop" (đó là hoạt động loại bỏ và trả về đỉnh của cấu trúc dữ liệu 'ngăn xếp'), thì pop()bản thân nó rất rõ ràng, trong khi pop(-1)có khả năng gây nhầm lẫn chính xác nó dư thừa.
coredumperror

a.pop (-1) để loại bỏ cái cuối cùng?
zx1986

14
@ zx1986 a poptrong hầu hết các ngôn ngữ lập trình thường loại bỏ mục cuối cùng, giống như trong Python. Vì vậy, cho dù bạn chỉ định -1 hoặc không có gì là giống nhau.
Pascal

30
Nhân tiện, pop()trả về bất cứ yếu tố nào nó loại bỏ.
Bob Stein

136

Giống như những người khác đã đề cập đến pop và del là những cách hiệu quả để loại bỏ một mục của chỉ mục đã cho. Tuy nhiên, chỉ vì mục đích hoàn thành (vì điều tương tự có thể được thực hiện thông qua nhiều cách trong Python):

Sử dụng các lát (điều này không thực hiện trong việc loại bỏ mục khỏi danh sách ban đầu):

(Ngoài ra, đây sẽ là phương pháp kém hiệu quả nhất khi làm việc với danh sách Python, nhưng điều này có thể hữu ích (nhưng không hiệu quả, tôi nhắc lại) khi làm việc với các đối tượng do người dùng xác định không hỗ trợ pop, nhưng vẫn xác định 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]

Lưu ý: Xin lưu ý rằng phương pháp này không sửa đổi danh sách tại chỗ như popdel. Nó thay vào đó tạo hai bản sao của danh sách (một từ đầu cho đến chỉ mục nhưng không có nó ( a[:index]) và một sau chỉ mục cho đến phần tử cuối cùng ( a[index+1:])) và tạo một đối tượng danh sách mới bằng cách thêm cả hai. Điều này sau đó được gán lại cho biến danh sách ( a). Do đó, đối tượng danh sách cũ bị hủy đăng ký và do đó rác được thu thập (với điều kiện đối tượng danh sách ban đầu không được tham chiếu bởi bất kỳ biến nào ngoài a).

Điều này làm cho phương pháp này rất không hiệu quả và nó cũng có thể tạo ra các tác dụng phụ không mong muốn (đặc biệt là khi các biến khác trỏ đến đối tượng danh sách ban đầu vẫn chưa được sửa đổi).

Cảm ơn @MarkDickinson đã chỉ ra điều này ...

Đây câu trả lời Stack Overflow giải thích các khái niệm về cắt.

Cũng lưu ý rằng điều này chỉ hoạt động với các chỉ số tích cực.

Trong khi sử dụng với các đối tượng, __getitem__phương thức phải được xác định và quan trọng hơn là __add__phương thức phải được xác định để trả về một đối tượng có chứa các mục từ cả hai toán hạng.

Về bản chất, điều này hoạt động với bất kỳ đối tượng nào có định nghĩa lớp giống như:

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 )

Điều này làm việc với listđịnh nghĩa __getitem____add__phương pháp.

So sánh ba cách về hiệu quả:

Giả sử sau đây được xác định trước:

a = range(10)
index = 3

Các del object[index]phương pháp:

Cho đến nay phương pháp hiệu quả nhất. Nó hoạt động sẽ tất cả các đối tượng xác định một __del__phương thức.

Việc tháo gỡ như sau:

Mã số:

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

Tháo gỡ:

 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 phương pháp:

Nó kém hiệu quả hơn phương thức del và được sử dụng khi bạn cần lấy mục đã xóa.

Mã số:

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

Tháo gỡ:

 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

Các lát cắt và thêm phương thức.

Ít hiệu quả nhất.

Mã số:

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

Tháo gỡ:

 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

Lưu ý: Trong cả ba phân tách, bỏ qua hai dòng cuối cùng về cơ bản là return None. Ngoài ra hai dòng đầu tiên đang tải các giá trị toàn cầu aindex.


4
Phương pháp cắt của bạn không xóa một phần tử khỏi danh sách: thay vào đó, nó tạo ra một đối tượng danh sách mới chứa tất cả trừ mục thứ i từ danh sách gốc. Danh sách ban đầu được để lại không thay đổi.
Đánh dấu Dickinson

@MarkDickinson Đã chỉnh sửa câu trả lời để làm rõ tương tự ... Xin vui lòng cho tôi biết nếu nó trông tốt bây giờ?
Raghav RV

6
Có thể câu trả lời không hoàn toàn thuộc về chủ đề, nhưng phương pháp lập chỉ mục rất hữu ích nếu bạn cần bỏ qua một mục từ một đối tượng không thay đổi, chẳng hạn như một tuple. pop () và del () sẽ không hoạt động trong trường hợp đó.
Caleb

6
@ rvraghav93 trong số tất cả các phương pháp được trình bày trong toàn bộ bài viết, a = a[:index] + a[index+1 :]-trick là thông minh nhất, khi nói đến danh sách khổng lồ. Tất cả các phương pháp khác đã kết thúc trong bế tắc. Cảm ơn bạn rất nhiều
user3085931

3
Thật vậy, Mark, bạn gắt gỏng. Câu trả lời này là câu tôi thích vì nó thực sự mang tính sư phạm. Tôi đã học được nhiều nhất từ ​​câu trả lời này và các chi tiết tháo gỡ được cung cấp và tác động đến hiệu suất. Cộng với phương pháp cắt, vâng, tạo một đối tượng khác, nhưng bây giờ nó được chỉ định và đôi khi đó cũng là những gì bạn cần.
Yohan Obadia

52

popcũng hữu ích để loại bỏ và giữ một mục từ danh sách. Trường hợp delthực sự bỏ rác các mặt hàng.

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

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

24

Nếu bạn muốn loại bỏ yếu tố vị trí cụ thể trong danh sách, như thứ 2, 3 và 7. bạn không thể sử dụng

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

Vì sau khi bạn xóa phần tử thứ hai, phần tử thứ ba bạn xóa thực sự là phần tử thứ tư trong danh sách gốc. Bạn có thể lọc phần tử thứ 2, 3 và 7 trong danh sách gốc và nhận danh sách mới, như bên dưới:

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

19

Điều này phụ thuộc vào những gì bạn muốn làm.

Nếu bạn muốn trả về phần tử bạn đã xóa, hãy sử dụng pop():

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

Tuy nhiên, nếu bạn chỉ muốn xóa một phần tử, hãy sử dụng del:

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

Ngoài ra, delcho phép bạn sử dụng các lát (ví dụ del[2:]).


18

Nói chung, tôi đang sử dụng phương pháp sau:

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

15

Tuy nhiên, một cách khác để loại bỏ (các) thành phần khỏi danh sách theo chỉ mục.

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] trỏ đến các phần tử từ chỉ mục xđến y-1. Khi chúng tôi khai báo phần đó của danh sách dưới dạng danh sách trống ( []), các phần tử đó sẽ bị xóa.


14

Bạn chỉ có thể tìm kiếm các mục bạn muốn xóa. Nó thực sự đơn giản. Thí dụ:

    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)

Đầu ra: acde


6
Tôi thích giải pháp này, nhưng tất nhiên nó cho rằng danh sách của bạn không có bản sao.
tommy.carstensen

11

Sử dụng mã sau để xóa phần tử khỏi danh sách:

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

output = [2, 3, 4]

Nếu bạn muốn xóa dữ liệu thành phần chỉ mục khỏi danh sách, hãy sử dụng:

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

2
Đi kèm với cảnh báo rằng danh sách của bạn không thể chứa các bản sao.
tommy.carstensen

3
Điều này không phải là loại bỏ bởi chỉ mục, mà là loại bỏ bởi giá trị phù hợp. Đó có thể là thông tin có giá trị đối với một số người truy cập tại đây, nhưng không cố gắng trả lời câu hỏi của OP.
Anthon

8

Như đã đề cập trước đây, thực hành tốt nhất là del (); hoặc pop () nếu bạn cần biết giá trị.

Một giải pháp thay thế là chỉ xếp lại các yếu tố bạn muốn:

    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 ... sẽ không hoạt động trên các giá trị chỉ số âm, sẽ suy ngẫm và cập nhật

tôi giả sử

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

sẽ vá nó ... nhưng đột nhiên ý tưởng này có vẻ rất dễ vỡ. Thử nghiệm thú vị mặc dù. Có vẻ nên có một cách 'phù hợp' để làm điều này với sự hiểu biết thêm () / danh sách.

suy ngẫm


1
Phiên bản nào của Python có chức năng del()? Đối với hàm đó, bạn cung cấp danh sách làm đối số đầu tiên cho hàm đó và sau đó là chỉ mục, hoặc chỉ mục trước và sau đó là danh sách? Liệu nó trả về đối số danh sách mà không có mục, hoặc nó thực hiện xóa tại chỗ. Tôi biết về delcâu lệnh, nhưng không phải về một hàm có cùng tên.
Anthon

8

Có vẻ như bạn không làm việc với một danh sách các danh sách, vì vậy tôi sẽ viết ngắn gọn. Bạn muốn sử dụng pop vì nó sẽ loại bỏ các yếu tố không phải là các yếu tố là danh sách, bạn nên sử dụng del cho điều đó. Để gọi phần tử cuối cùng trong python là "-1"

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

1
pop()delcả hai loại bỏ một phần tử tại chỉ mục được cung cấp, độc lập với việc phần tử đó có phải là một danh sách hay không. a = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b
Anthon

8

l - danh sách các giá trị; chúng ta phải xóa các chỉ mục khỏi danh sách 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]

không hoạt động, câu trả lời là <map at 0x7f4d54109a58>. và l là phạm vi (0,20)
Hitesh

7

Sử dụng chức năng "del" :

del listName[-N]

Ví dụ: nếu bạn muốn xóa 3 mục cuối, mã của bạn phải là:

del listName[-3:]

Ví dụ: nếu bạn muốn xóa 8 mục cuối, mã của bạn phải là:

del listName[-8:]

2
dellà một tuyên bố . Nếu đó là một chức năng, bạn sẽ phải viếtdel(listame[-N])
Anthon

7

Nó đã được đề cập làm thế nào để loại bỏ một yếu tố duy nhất khỏi danh sách và lợi thế của các phương pháp khác nhau có. Tuy nhiên, lưu ý rằng việc xóa nhiều phần tử có một số lỗi tiềm ẩn:

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

Các yếu tố 3 và 8 (không phải 3 và 7) của danh sách ban đầu đã bị xóa (vì danh sách đã được rút ngắn trong vòng lặp), có thể không phải là ý định. Nếu bạn muốn xóa một cách an toàn nhiều chỉ mục, trước tiên bạn nên xóa các phần tử có chỉ mục cao nhất, ví dụ như thế này:

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

Hoặc nếu nhiều chỉ mục cần được loại bỏ:

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

Tất nhiên sau đó cũng có thể làm:

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

1
Tại sao bạn không sắp xếp danh sách các chỉ mục theo thứ tự ngược lại và sau đó xóa từng chỉ số một? Bằng cách đó, bạn không phải tạo một danh sách mới.
Anthon

3

Bạn có thể sử dụng del hoặc pop để xóa phần tử khỏi danh sách dựa trên chỉ mục. Pop sẽ in thành viên mà nó đang xóa khỏi danh sách, trong khi danh sách xóa thành viên đó mà không in nó.

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

3

Người ta có thể sử dụng del hoặc pop, nhưng tôi thích del hơn, vì bạn có thể chỉ định chỉ mục và lát, cho phép người dùng kiểm soát dữ liệu nhiều hơn.

Ví dụ, bắt đầu với danh sách được hiển thị, người ta có thể loại bỏ phần tử cuối cùng của nó deldưới dạng một lát cắt, và sau đó người ta có thể loại bỏ phần tử cuối cùng khỏi kết quả bằng cách sử dụng pop.

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.