Apakah ada cara sederhana untuk menghapus elemen daftar berdasarkan nilai?

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

del a[b]
print(a)

Di atas menunjukkan kesalahan berikut:

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

Jadi saya harus melakukan ini:

a = [1, 2, 3, 4]

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

print(a)

Tetapi apakah tidak ada cara yang lebih sederhana untuk melakukan ini?

zjm1126
sumber
14
Anda menghitung indeks 6 dalam daftar Anda. Tapi 6 tidak ada dalam daftar Anda ... jadi apa yang seharusnya terjadi? :)
Johannes Charra
5
ini tidak ada hubungannya dengan menghapus nilai dalam daftar, karena kode Anda tidak mencapai pernyataan del. Mungkin Anda harus memberi judul ulang "bagaimana saya mendapatkan indeks nilai yang tidak ada dalam daftar. Jawaban yang jelas - Anda tidak bisa.
Dave Kirby
57
@ Selamat Yah, tidak juga. Dia ingin menghapus item dari daftar terlepas dari apakah itu ada atau tidak, tidak untuk mendapatkan indeks untuk item yang tidak ada. Pertanyaannya ditanyakan dengan baik.
ibz
Selain itu, tetapi telanjang exceptadalah praktik yang buruk . Gunakan except Exceptionminimal.
wjandrea

Jawaban:

1564

Untuk menghapus kejadian pertama suatu elemen dalam daftar, cukup gunakan list.remove:

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

Pikiran bahwa itu tidak menghapus semua kemunculan elemen Anda. Gunakan pemahaman daftar untuk itu.

>>> 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]
Johannes Charra
sumber
144
Gagal jika elemen tidak ada dalam daftar. :)
ibz
21
Pemahaman daftar @ibz tidak gagal bahkan jika elemen tidak ada dalam daftar, bukan?
IsaacS
76
Untuk memperjelas bagi siapa pun yang membaca sepintas lalu, itu "gagal" dalam arti bahwa hal itu menimbulkan pengecualian ValueError.
Casey Falk
10
Pemahaman daftar mengubah referensi daftar jadi jika ada salinan referensi di suatu tempat, penghapusan tidak akan mengikuti.
Sebastien
Apa kerumitannya removeO (n)?
Rasmi Ranjan Nayak
184

Biasanya Python akan mengeluarkan Exception jika Anda menyuruhnya melakukan sesuatu yang tidak bisa, jadi Anda harus melakukannya:

if c in a:
    a.remove(c)

atau:

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

Pengecualian tidak selalu merupakan hal yang buruk asalkan itu yang Anda harapkan dan tangani dengan benar.

Dave Webb
sumber
9
Mencegah lebih baik daripada mengobati. Jika Anda dapat memeriksa kondisi luar biasa terlebih dahulu (contoh a), Anda harus melakukannya.
Gusdor
82
Sementara ini benar dalam bahasa lain, dalam Python itu "lebih mudah untuk meminta pengampunan daripada izin." docs.python.org/2/glossary.html#term-eafp
Dave Webb
6
@ Goddor: jika daftar dibagikan di antara utas-utas maka a.remove(c)mungkin akan gagal meskipun if c in acek ( adapat dimodifikasi di utas lain setelah c in acek tetapi sebelum a.remove(c)panggilan) try/exceptatau kunci dapat digunakan untuk menghindari kondisi balapan.
jfs
7
@ JSFSebastian jika daftar dibagi di antara utas dan Anda tidak menerapkan bagian kritis maka Anda memiliki masalah yang lebih besar.
Gusdor
4
@ Goddor, idiom Pythonique adalah mencoba tanpa memeriksa dan menangkap pengecualian jika itu terjadi. Ini lebih efisien (hanya satu pencarian, bukan dua), meskipun sedikit lebih buruk
Jeet
80

Anda dapat melakukan

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

tetapi di atas perlu mencari 6 dalam daftar 2 kali, jadi coba kecuali akan lebih cepat

try:
    a.remove(6)
except:
    pass
KAMU
sumber
55

Mempertimbangkan:

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

Untuk menghapus semua kejadian, Anda bisa menggunakan fungsi filter dengan python. Sebagai contoh, akan terlihat seperti:

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

Jadi, itu akan menjaga semua elemen a != 2.

Untuk hanya mengambil salah satu item yang digunakan

a.remove(2)
mathwizurd
sumber
Mengapa Anda membungkus yang filter()lain list()? Menurut manual, itu sudah mengembalikan daftar.
Olaf Dietsche
8
@ OlafDietsche Dalam Python 3.x, ia mengembalikan objek filter (dalam 2.x, ia mengembalikan daftar), jadi saya harus melemparkan "a" ke daftar agar dapat memiliki fungsionalitas.
mathwizurd
17

Berikut cara melakukannya di tempat (tanpa pemahaman daftar):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]
jfs
sumber
Sangat pintar - saya sangat suka ini - sayangnya sepertinya tidak efisien seperti jawaban paling populer. solusi gil sebenarnya jauh lebih cepat untuk daftar raksasa dengan hanya beberapa kemunculan nilai yang ingin Anda hapus.
Larold
1
@Larold Cara tercepat adalah pertanyaan terpisah. Uang saya masuk daftar pemahaman dalam kasus umum. Solusi ini harus berkinerja sangat baik jika nilainya sering dalam daftar input dan pemahaman daftar tidak digunakan. Coba Pypy, data numpy di Cython. [@ Gill jawaban O(n*n)tidak perlu (bandingkan 1e6 dan 1e12 - Anda tidak ingin mengambil risiko yang terakhir). while 1: L.remove(value)dan kembali ValueErrormungkin bekerja dengan baik dengan beberapa values atau daftar kecil di CPython.
jfs
13

Jika Anda tahu nilai apa yang harus dihapus, berikut ini cara sederhana (sesederhana yang dapat saya pikirkan):

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

Anda akan mendapatkannya [0, 0, 2, 3, 4]

gil
sumber
4
Mengapa tidak digunakan while 1 in a:sebagai struktur loop?
TerminalDilettante
12
Di O(n^2)sinilah pemahaman akan terjadi O(n).
Fisikawan Gila
1
Tentu saja @MadPhysicist benar, dan versi TerminalDilettante jauh lebih pythonic, bahkan jika kita tidak peduli dengan kinerja. 2013 adalah saya baru mulai belajar Python dan saat ini saya cukup malu dengan apa yang saya tulis saat itu.
gil
11

Kemungkinan lain adalah menggunakan set daripada daftar, jika satu set berlaku di aplikasi Anda.

Yaitu jika data Anda tidak diurutkan, dan tidak memiliki duplikat, maka

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

bebas dari kesalahan.

Seringkali daftar hanyalah wadah berguna untuk item yang sebenarnya tidak terurut. Ada pertanyaan yang menanyakan cara menghapus semua kemunculan elemen dari daftar. Jika Anda tidak ingin dupes di tempat pertama, sekali lagi satu set berguna.

my_set.add(3)

tidak mengubah my_set dari atas.

GreenAsJade
sumber
10

Seperti yang dinyatakan oleh banyak jawaban lain, list.remove()akan berhasil, tetapi melempar ValueErrorjika item tidak ada dalam daftar. Dengan python 3.4+, ada pendekatan yang menarik untuk menangani ini, menggunakan suppress contextmanager :

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

Menemukan nilai dalam daftar lalu menghapus indeks itu (jika ada) lebih mudah dilakukan dengan hanya menggunakan metode hapus daftar:

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

Jika Anda sering melakukannya, Anda dapat membungkusnya dalam suatu fungsi:

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

sumber
8

Contoh ini cepat dan akan menghapus semua instance nilai dari daftar:

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]
Chase Adams
sumber
2
jika Anda melakukan ini, Anda harus benar-benar hanya breakpada except ValueError.
Anthon
8

Dalam satu baris:

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

terkadang bermanfaat.

Lebih mudah lagi:

if 'b' in a: a.remove('b')
Andrey Suglobov
sumber
7

Jika elemen Anda berbeda, maka perbedaan set sederhana akan dilakukan.

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]
Pagol
sumber
2
Jika elemen Anda berbeda dan Anda tidak peduli tentang pesanan .
Tom Zych
2

Kita juga bisa menggunakan .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]
>>> 
SuperNova
sumber
2

Timpa daftar dengan mengindeks semuanya kecuali elemen yang ingin Anda hapus

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

Dengan for for dan kondisi:

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

Dan jika Anda ingin menghapus beberapa, tetapi tidak semua:

def cleaner(seq, value, occ):
    temp = []
    for number in seq:
        if number == value and occ:
            occ -= 1
            continue
        else:
            temp.append(number)
    return temp
pengguna7970984
sumber
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)
Ravikiran D
sumber
Itu tanpa menggunakan fungsi filter
Ravikiran D
1

Katakan misalnya, kami ingin menghapus semua 1 dari x. Ini adalah bagaimana saya akan melakukannya:

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

Sekarang, ini adalah penggunaan praktis dari metode saya:

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

Dan ini adalah metode saya dalam satu baris:

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

Keduanya menghasilkan ini sebagai output:

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

Semoga ini membantu. PS, mohon perhatikan bahwa ini ditulis dalam versi 3.6.2, jadi Anda mungkin perlu menyesuaikannya untuk versi yang lebih lama.

Krohnus Melavea
sumber
1

Mungkin solusi Anda bekerja dengan ints, tetapi itu tidak berfungsi untuk saya dengan kamus.

Di satu sisi, hapus () tidak berfungsi untuk saya. Tapi mungkin itu bekerja dengan Tipe dasar. Saya kira kode di bawah ini juga cara untuk menghapus item dari daftar objek.

Di sisi lain, 'del' juga tidak berfungsi dengan baik. Dalam kasus saya, menggunakan python 3.6: ketika saya mencoba untuk menghapus elemen dari daftar di 'for' bucle dengan perintah 'del', python mengubah indeks dalam proses dan bucle berhenti sebelum waktunya sebelum waktu. Ini hanya berfungsi jika Anda menghapus elemen demi elemen secara terbalik urutan . Dengan cara ini Anda tidak mengubah indeks array elemen yang menunggu saat Anda akan melewatinya

Kemudian, saya menggunakan:

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

di mana 'daftar' seperti [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Anda juga dapat melakukan lebih banyak pythonic menggunakan enumerate:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)
David Martínez
sumber
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]
Brijesh Kushwaha
sumber
0

Ini menghapus semua instance dari "-v"array sys.argv, dan tidak mengeluh jika tidak ada instance ditemukan:

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

Anda dapat melihat kode dalam aksi, dalam file bernama 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']
Mike Slinn
sumber
-1

ini jawaban saya, gunakan saja sementara dan untuk

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()
guoxy2016
sumber