Câu hỏi Làm cách nào để xóa một phần tử khỏi danh sách theo chỉ mục bằng Python?


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

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


1054
2018-03-09 18:16


gốc


Câu trả lời có thể mở rộng là sử dụng collections.deque - smci
@smci: xóa ở giữa là O (n) cho dù đó là một danh sách hoặc deque. - jfs
Có @ j-f-sebastian, bạn đã đúng. Sau đó tôi phát hiện ra rằng deque chỉ cải thiện khả năng mở rộng của chèn; không tra cứu (O (1)) hoặc xóa. Tôi đã xóa câu trả lời sai. Tuy nhiên tôi nghĩ (danh sách) xóa-by-index chỉ là một tra cứu theo sau là xóa (và tái phân bổ bộ nhớ nội bộ), vì vậy chắc chắn họ đang O (1) không O (n)? Việc xóa theo giá trị thực sự là O (n) vì chúng liên quan đến việc truyền tải. - smci
@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 để loại bỏ khoảng trống đó là lý do tại sao nó O(n) trong thời gian hoạt động. deque() cung cấp các hoạt động hiệu quả trên cả hai đầu nhưng nó không cung cấp O (1) chèn / tra / xóa ở giữa. - jfs
@ J.F.Sebastian: cPython thực hiện, có, cảm ơn đã sửa tôi. Đúng thông số ngôn ngữ không chỉ định cách triển khai danh sách, các triển khai thay thế có thể chọn sử dụng danh sách được liên kết. - smci


Các câu trả lời:


Sử dụng del và 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.


1216
2018-03-09 18:21



Cảm ơn, sự khác biệt giữa pop và del là gì? - Joan Venge
del bị quá tải. Ví dụ del xóa toàn bộ danh sách - Brian R. Bondy
một ví dụ khác del a [2: 4], xóa các phần tử 2 và 3 - Brian R. Bondy
pop () trả về phần tử bạn muốn xóa. del chỉ xóa là.
Tôi không thể thấy bằng chứng về "danh sách được liên kết" ở đó. Nhìn vào svn.python.org/projects/python/trunk/Objects/listobject.c làm sao PyList_GetItem() về cơ bản trả về ((PyListObject *)op) -> ob_item[i]; - các iphần tử thứ của một mảng. - glglgl


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, pop mà không có bất kỳ đối số nào xóa mục cuối cùng:

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

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

490
2018-03-09 18:17



Đừng quên pop (-1). Có, đó là mặc định, nhưng tôi thích nó vì vậy tôi không cần phải nhớ pop cuối cùng sử dụng theo mặc định. - S.Lott
Điểm tốt ... làm tăng khả năng đọc. - Jarret Hardie
Tôi không đồng ý. Nếu bạn biết từ nguyên của lập trình viên là "pop" (đó là hoạt động loại bỏ và trả về hàng đầu của cấu trúc dữ liệu 'ngăn xếp'), sau đó pop() bởi chính nó là rất rõ ràng, trong khi pop(-1) có khả năng gây nhầm lẫn chính xác bởi vì nó dư thừa. - CoreDumpError
@ zx1986 a pop trong hầu hết các ngôn ngữ lập trình thường loại bỏ mục cuối cùng, như trong Python. Vì vậy, cho dù bạn chỉ định -1 hoặc không có gì là như nhau. - Pascal
Nhân tiện, pop() trả về bất kỳ phần tử nào nó đã xóa. - Bob Stein


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

Sử dụng lát (điều này không thực hiện việc xóa mục khỏi danh sách gốc):

(Ngoài ra, đây sẽ là phương pháp 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 định nghĩa không hỗ trợ pop, __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]

Chú thích: Xin lưu ý rằng phương pháp này không sửa đổi danh sách tại chỗ như pop và del. Thay vào đó, nó tạo ra hai bản sao của các danh sách (một từ đầu cho đến khi chỉ mục mà không có nó)a[:index]) và một sau khi chỉ mục đến phần tử cuối cùng (a[index+1:])) và tạo đố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ũ do đó bị hủy đăng ký và do đó được thu thập rác (miễn là đối tượng danh sách ban đầu không được tham chiếu bởi bất kỳ biến nào khác ngoài một biến).

Điều này làm cho phương pháp này rất kém 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).

Nhờ @MarkDickinson đã chỉ ra điều này ...

Điều này Stack Overflow answer giải thích khái niệm về slicing.

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 pháp phải được xác định và quan trọng hơn là __add__ phương thức phải được định nghĩa để trả về một đối tượng chứa các mục từ cả hai toán hạng.

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

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 xác định __getitem__ và __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:

Đến nay là 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 __del__ phương pháp.

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 pháp 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 và thêm phương pháp.

Hiệu quả thấp 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 lần ngắt, 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 a và index.


96
2018-06-22 15:21



Phương pháp cắt của bạn không xóa phần tử khỏi danh sách: thay vào đó, nó sẽ tạo Mới liệt kê đối tượng chứa tất cả trừ mục nhập thứ i từ danh sách gốc. Danh sách gốc không được sửa đổi. - Mark Dickinson
@MarkDickinson Đã chỉnh sửa câu trả lời để làm rõ điều tương tự ... Vui lòng cho tôi biết nếu nó có vẻ tốt không? - Raghav RV
Có lẽ câu trả lời không hoàn toàn 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 bất biến, chẳng hạn như một bộ tuple. pop () và del () sẽ không hoạt động trong trường hợp đó. - Caleb
@ rvraghav93 trong số tất cả các phương pháp được trình bày trong toàn bộ bài đăng, a = a[:index] + a[index+1 :]-trick là người hiểu biết nhất, khi nói đến các danh sách lớn. Tất cả các phương pháp khác kết thúc trong một bế tắc. Cảm ơn rất nhiều - user3085931
Thật vậy Mark, bạn đang gắt gỏng. Câu trả lời này là câu trả lời tôi thích vì nó thực sự là 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 performanc. Cộng với phương pháp cắt, có, tạo một đối tượng khác, nhưng bây giờ nó được xác định và đôi khi đó cũng là những gì bạn cần. - Yohan Obadia


pop cũng hữu ích để loại bỏ và giữ một mục từ danh sách. Ở đâu delthực sự trashes item.

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

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

42
2017-10-19 13:10



Bởi vì câu trả lời trước đó từ 4 năm trước đã không đề cập đến pop trả về giá trị đã xóa. Nó chỉ cho thấy nó loại bỏ giá trị từ danh sách. Như trái ngược với del mà thực sự loại bỏ nó mà không cho bạn một bản sao của nó. Không có bình luận nào đề cập đến nó. - boatcoder


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]

12
2017-10-05 12:23





Đ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ả lại 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, del cho phép bạn sử dụng lát (ví dụ: del[2:]).


10
2017-08-11 00:17





Tuy nhiên, một cách khác để xóa (các) phần tử 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]

một [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 ([]), những yếu tố đó bị xóa.


6
2017-10-30 09:21



Tôi thích điều này, cảm ơn! - jacktrader