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ư pop
và del
. 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__
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:
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 a
và index
.
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.