Có một cách đơn giản để xóa một yếu tố danh sách theo giá trị?


942
a = [1, 2, 3, 4]
b = a.index(6)

del a[b]
print(a)

Trên đây cho thấy lỗi sau:

Traceback (most recent call last):
  File "D:\zjm_code\a.py", line 6, in <module>
    b = a.index(6)
ValueError: list.index(x): x not in list

Vì vậy, tôi phải làm điều này:

a = [1, 2, 3, 4]

try:
    b = a.index(6)
    del a[b]
except:
    pass

print(a)

Nhưng không có cách nào đơn giản hơn để làm điều này?


14
Bạn tính chỉ số 6 trong danh sách của bạn. Nhưng 6 không có trong danh sách của bạn ... vậy điều gì sẽ xảy ra? :)
Julian Charra

5
điều này không liên quan gì đến việc xóa một giá trị trong danh sách, vì mã của bạn không đạt được câu lệnh del. Có lẽ bạn nên đặt lại tên cho nó "làm thế nào để tôi có được chỉ số của một giá trị không có trong danh sách. Câu trả lời rõ ràng - bạn không thể.
Dave Kirby

57
@Dave Vâng, không thực sự. Anh ta muốn xóa một mục khỏi danh sách bất kể nó có tồn tại hay không, không lấy chỉ mục cho một mục không tồn tại. Câu hỏi được hỏi tốt.
ibz

Bên cạnh quan điểm, nhưng một trần exceptlà thực hành xấu . Sử dụng except Exceptionở mức tối thiểu.
wjandrea

Câu trả lời:


1564

Để xóa lần xuất hiện đầu tiên của một thành phần trong danh sách, chỉ cần sử dụng list.remove:

>>> a = ['a', 'b', 'c', 'd']
>>> a.remove('b')
>>> print(a)
['a', 'c', 'd']

Lưu ý rằng nó không loại bỏ tất cả các lần xuất hiện của phần tử của bạn. Sử dụng một danh sách hiểu cho điều đó.

>>> a = [10, 20, 30, 40, 20, 30, 40, 20, 70, 20]
>>> a = [x for x in a if x != 20]
>>> print(a)
[10, 30, 40, 30, 40, 70]

144
Thất bại nếu phần tử không có trong danh sách. :)
ibz

21
Hiểu danh sách @ibz không thất bại ngay cả khi phần tử không có trong danh sách, phải không?
IsaacS

76
Để làm rõ cho bất kỳ ai lướt qua, nó "thất bại" theo nghĩa là nó làm tăng ngoại lệ ValueError.
Casey Falk

10
Việc hiểu danh sách thay đổi tham chiếu danh sách để nếu có một bản sao của tài liệu tham khảo ở đâu đó, việc xóa sẽ không tuân theo.
Sebastien

Độ phức tạp của removenó là O (n) là gì?
Rasmi Ranjan Nayak

184

Thông thường Python sẽ ném Ngoại lệ nếu bạn bảo nó làm điều gì đó không thể, do đó bạn sẽ phải làm:

if c in a:
    a.remove(c)

hoặc là:

try:
    a.remove(c)
except ValueError:
    pass

Một ngoại lệ không nhất thiết là một điều xấu miễn là bạn đang mong đợi và xử lý đúng cách.


9
Phòng bệnh hơn chữa bệnh. Nếu bạn có thể kiểm tra các điều kiện đặc biệt trước tiên (ví dụ a), bạn nên.
Gusdor

82
Mặc dù điều này đúng trong các ngôn ngữ khác, nhưng trong Python, "dễ dàng yêu cầu sự tha thứ hơn là sự cho phép". docs.python.org/2/glossary.html#term-eafp
Dave Webb

6
@Gusdor: nếu danh sách được chia sẻ giữa các luồng thì a.remove(c)dù sao cũng có thể thất bại mặc dù if c in akiểm tra ( acó thể được sửa đổi trong một luồng khác sau khi c in akiểm tra nhưng trước a.remove(c)cuộc gọi). try/excepthoặc khóa có thể được sử dụng để tránh điều kiện cuộc đua.
jfs

7
@JFSebastian nếu một danh sách được chia sẻ giữa các luồng và bạn không áp dụng các phần quan trọng thì bạn có vấn đề lớn hơn.
Gusdor

4
@Gusdor, thành ngữ Pythonique là thử mà không kiểm tra và bắt ngoại lệ nếu nó xảy ra. Nó hiệu quả hơn (chỉ một lần tra cứu thay vì hai), mặc dù xấu hơn một chút
Jeet

80

Bạn có thể làm

a=[1,2,3,4]
if 6 in a:
    a.remove(6)

nhưng ở trên cần tìm kiếm 6 trong danh sách 2 lần, vì vậy hãy thử ngoại trừ sẽ nhanh hơn

try:
    a.remove(6)
except:
    pass

55

Xem xét:

a = [1,2,2,3,4,5]

Để loại bỏ tất cả các lần xuất hiện, bạn có thể sử dụng chức năng lọc trong python. Ví dụ, nó sẽ trông như:

a = list(filter(lambda x: x!= 2, a))

Vì vậy, nó sẽ giữ tất cả các yếu tố của a != 2.

Để lấy ra một trong những vật phẩm sử dụng

a.remove(2)

Tại sao bạn bọc filter()trong một list()cái khác ? Theo hướng dẫn, nó đã trả về một danh sách.
Olaf Dietsche

8
@OlafDietsche Trong Python 3.x, nó trả về một đối tượng bộ lọc (trong 2.x, nó trả về một danh sách), vì vậy tôi phải chuyển "a" sang danh sách để nó có bất kỳ chức năng nào.
mathwizurd

17

Đây là cách thực hiện tại chỗ (không có danh sách hiểu):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]

Rất thông minh - Tôi thực sự thích điều này - thật không may, nó dường như không hiệu quả như câu trả lời phổ biến nhất. Giải pháp của gil thực sự nhanh hơn nhiều đối với các danh sách khổng lồ chỉ với một vài lần xuất hiện của giá trị bạn muốn xóa.
Larold

1
@Larold Cách nhanh nhất sẽ là một câu hỏi riêng biệt. Tiền của tôi nằm trong danh sách hiểu trong trường hợp chung. Giải pháp này sẽ thực hiện tốt nếu giá trị thường xuyên trong danh sách đầu vào và việc hiểu danh sách không được sử dụng. Hãy thử dữ liệu Pypy, numpy trong Cython. [@ Câu trả lời của Gill là O(n*n)không cần thiết (so sánh 1e6 và 1e12 - bạn không muốn mạo hiểm sau này). while 1: L.remove(value)và trở lại ValueErrorcó thể hoạt động tốt với một vài valuedanh sách nhỏ hoặc nhỏ trong CPython.
jfs

13

Nếu bạn biết giá trị nào cần xóa, thì đây là một cách đơn giản (dù sao tôi cũng có thể nghĩ ra)

a = [0, 1, 1, 0, 1, 2, 1, 3, 1, 4]
while a.count(1) > 0:
    a.remove(1)

Bạn sẽ nhận được [0, 0, 2, 3, 4]


4
Tại sao không sử dụng while 1 in a:như cấu trúc vòng lặp?
TerminalDilettante

12
Đây là O(n^2)nơi một sự hiểu biết sẽ được O(n).
Nhà vật lý điên

1
Tất nhiên @MadPhysicist là đúng, và phiên bản của TerminalDilettante là nhiều pythonic hơn, ngay cả khi chúng ta không quan tâm đến hiệu suất. Năm 2013 tôi mới bắt đầu học Python và ngày nay tôi khá xấu hổ về những gì tôi đã viết hồi đó.
gil

11

Một khả năng khác là sử dụng một bộ thay vì danh sách, nếu một bộ được áp dụng trong ứng dụng của bạn.

IE nếu dữ liệu của bạn không được đặt hàng và không có trùng lặp, thì

my_set=set([3,4,2])
my_set.discard(1)

không có lỗi

Thường thì một danh sách chỉ là một thùng chứa tiện dụng cho các vật phẩm thực sự không có thứ tự. Có những câu hỏi làm thế nào để loại bỏ tất cả sự xuất hiện của một yếu tố khỏi danh sách. Nếu bạn không muốn bị lừa ở nơi đầu tiên, một lần nữa một bộ sẽ tiện dụng.

my_set.add(3)

không thay đổi my_set từ trên.


10

Như đã nêu trong nhiều câu trả lời khác, list.remove()sẽ có hiệu quả, nhưng hãy ném ValueErrornếu mục đó không có trong danh sách. Với python 3.4 trở lên, có một cách tiếp cận thú vị để xử lý này, bằng cách sử dụng contextmanager đàn áp :

from contextlib import suppress
with suppress(ValueError):
    a.remove('b')

8

Tìm một giá trị trong danh sách và sau đó xóa chỉ mục đó (nếu nó tồn tại) được thực hiện dễ dàng hơn bằng cách chỉ sử dụng phương thức xóa danh sách:

>>> a = [1, 2, 3, 4]
>>> try:
...   a.remove(6)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 3, 4]
>>> try:
...   a.remove(3)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 4]

Nếu bạn làm điều này thường xuyên, bạn có thể gói nó trong một chức năng:

def remove_if_exists(L, value):
  try:
    L.remove(value)
  except ValueError:
    pass

8

Ví dụ này nhanh và sẽ xóa tất cả các phiên bản của một giá trị khỏi danh sách:

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]

2
Nếu bạn làm điều này, bạn thực sự chỉ nên breaktrên except ValueError.
Anthon

8

Trong một dòng:

a.remove('b') if 'b' in a else None

đôi khi nó hữu ích

Thậm chí dễ dàng hơn:

if 'b' in a: a.remove('b')

7

Nếu các yếu tố của bạn là khác biệt, thì một sự khác biệt thiết lập đơn giản sẽ làm.

c = [1,2,3,4,'x',8,6,7,'x',9,'x']
z = list(set(c) - set(['x']))
print z
[1, 2, 3, 4, 6, 7, 8, 9]

2
Nếu các yếu tố của bạn là khác biệt và bạn không quan tâm đến trật tự .
Tom Zych

2

Chúng tôi cũng có thể sử dụng .pop:

>>> lst = [23,34,54,45]
>>> remove_element = 23
>>> if remove_element in lst:
...     lst.pop(lst.index(remove_element))
... 
23
>>> lst
[34, 54, 45]
>>> 

2

Ghi đè danh sách bằng cách lập chỉ mục mọi thứ trừ các yếu tố bạn muốn xóa

>>> s = [5,4,3,2,1]
>>> s[0:2] + s[3:]
[5, 4, 2, 1]

2

Với một vòng lặp for và một điều kiện:

def cleaner(seq, value):    
    temp = []                      
    for number in seq:
        if number != value:
            temp.append(number)
    return temp

Và nếu bạn muốn xóa một số, nhưng không phải tất cả:

def cleaner(seq, value, occ):
    temp = []
    for number in seq:
        if number == value and occ:
            occ -= 1
            continue
        else:
            temp.append(number)
    return temp

1
 list1=[1,2,3,3,4,5,6,1,3,4,5]
 n=int(input('enter  number'))
 while n in list1:
    list1.remove(n)
 print(list1)

Đó là không sử dụng chức năng lọc
Ravikiran D

1

Ví dụ, chúng tôi muốn xóa tất cả 1 khỏi x. Đây là cách tôi sẽ đi về nó:

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

Bây giờ, đây là một cách sử dụng thực tế phương pháp của tôi:

def Function(List, Unwanted):
    [List.remove(Unwanted) for Item in range(List.count(Unwanted))]
    return List
x = Function(x, 1)
print(x)

Và đây là phương pháp của tôi trong một dòng duy nhất:

[x.remove(1) for Item in range(x.count(1))]
print(x)

Cả hai đều mang lại kết quả này như một đầu ra:

[2, 3, 2, 3, 2, 3]

Hi vọng điêu nay co ich. PS, xin lưu ý rằng điều này đã được viết trong phiên bản 3.6.2, vì vậy bạn có thể cần điều chỉnh nó cho các phiên bản cũ hơn.


1

Có thể các giải pháp của bạn hoạt động với ints, nhưng Nó không hoạt động với tôi với từ điển.

Trong một tay, remove () đã không làm việc cho tôi. Nhưng có lẽ nó hoạt động với các loại cơ bản. Tôi đoán mã dưới đây cũng là cách để loại bỏ các mục khỏi danh sách đối tượng.

Mặt khác, 'del' cũng không hoạt động đúng. Trong trường hợp của tôi, sử dụng python 3.6: khi tôi cố gắng xóa một phần tử khỏi danh sách trong lệnh 'for' bucle with 'del', python thay đổi chỉ mục trong quy trình và các hạt nhân dừng sớm trước thời gian. Nó chỉ hoạt động nếu bạn xóa phần tử theo phần tử theo thứ tự đảo ngược . Theo cách này, bạn không thay đổi chỉ số mảng phần tử đang chờ xử lý khi bạn đang trải qua nó

Sau đó, tôi đã sử dụng:

c = len(list)-1
for element in (reversed(list)):
    if condition(element):
        del list[c]
    c -= 1
print(list)

trong đó 'list' giống như [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Ngoài ra, bạn có thể thực hiện nhiều pythonic hơn bằng cách sử dụng liệt kê:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)

0
arr = [1, 1, 3, 4, 5, 2, 4, 3]

# to remove first occurence of that element, suppose 3 in this example
arr.remove(3)

# to remove all occurences of that element, again suppose 3
# use something called list comprehension
new_arr = [element for element in arr if element!=3]

# if you want to delete a position use "pop" function, suppose 
# position 4 
# the pop function also returns a value
removed_element = arr.pop(4)

# u can also use "del" to delete a position
del arr[4]

0

Điều này loại bỏ tất cả các phiên bản của "-v"mảng sys.argvvà không khiếu nại nếu không tìm thấy trường hợp nào:

while "-v" in sys.argv:
    sys.argv.remove('-v')

Bạn có thể thấy mã đang hoạt động, trong một tệp có tên speechToText.py:

$ python speechToText.py -v
['speechToText.py']

$ python speechToText.py -x
['speechToText.py', '-x']

$ python speechToText.py -v -v
['speechToText.py']

$ python speechToText.py -v -v -x
['speechToText.py', '-x']

-1

đây là câu trả lời của tôi, chỉ cần sử dụng trong khicho

def remove_all(data, value):
    i = j = 0
    while j < len(data):
        if data[j] == value:
            j += 1
            continue
        data[i] = data[j]
        i += 1
        j += 1
    for x in range(j - i):
        data.pop()
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.