Hapus beberapa item dari daftar Python hanya dalam satu pernyataan

107

Dengan python, saya tahu cara menghapus item dari daftar.

item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)

Kode di atas ini menghapus nilai 5 dan 'item' dari item_list. Tetapi ketika ada banyak hal yang harus dihapus, saya harus menulis banyak baris

item_list.remove("something_to_remove")

Jika saya mengetahui indeks dari apa yang saya hapus, saya menggunakan:

del item_list[x]

dimana x adalah indeks dari item yang ingin saya hapus.

Jika saya mengetahui indeks dari semua angka yang ingin saya hapus, saya akan menggunakan semacam perulangan ke delitem di indeks.

Tetapi bagaimana jika saya tidak tahu indeks item yang ingin saya hapus?

Saya mencoba item_list.remove('item', 'foo'), tetapi saya mendapat kesalahan yang mengatakan itu removehanya membutuhkan satu argumen.

Adakah cara untuk menghapus beberapa item dari daftar dalam satu pernyataan?

PS Saya telah menggunakan deldan remove. Bisakah seseorang menjelaskan perbedaan antara keduanya, atau apakah mereka sama?

Terima kasih

RandomCoder
sumber
1
Untuk menjawab pertanyaan kedua Anda: delhapus item dengan indeksnya. The removeFungsi daftar menemukan indeks item dan kemudian memanggil delpada indeks itu.
Aaron Christiansen
Kemungkinan duplikat Menghapus beberapa elemen dari daftar
IMLD

Jawaban:

161

Di Python, membuat objek baru seringkali lebih baik daripada memodifikasi yang sudah ada:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

Yang mana setara dengan:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
    if e not in ('item', 5):
        new_list.append(e)
item_list = new_list

Dalam kasus daftar besar nilai yang disaring (di sini, ('item', 5)adalah sekumpulan kecil elemen), gunakan a setdapat mengarah pada peningkatan kinerja, karena inoperasinya ada di O (1):

item_list = [e for e in item_list if e not in {'item', 5}]

Perhatikan bahwa, seperti yang dijelaskan dalam komentar dan disarankan di sini , hal berikut dapat menghemat lebih banyak waktu, menghindari set yang akan dibuat pada setiap loop:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

Sebuah Filter mekar juga merupakan solusi yang baik jika memori tidak murah.

aluriak
sumber
Saya suka jawaban pertama. Saya tidak membuat daftar baru, itu bagus. Terima kasih!
RandomCoder
Apakah set dioptimalkan di python 2 atau hanya dioptimalkan di python 3? Yang saya maksud adalah set dibuat hanya sekali ketika bytecode dibuat?
Har
Set, menurut definisi , dioptimalkan untuk inpengoperasian. Lihat tolok ukur ini untuk perbandingan empat struktur data primitif. Ya, himpunan dibangun di setiap loop, seperti yang disarankan di sini , akibatnya menyimpan himpunan dalam variabel khusus untuk digunakan dalam ekspresi generator dapat menghemat waktu.
aluriak
@RandomCoder Anda benar-benar membuat daftar baru, Anda cukup menggunakan nama kembali. Anda dapat memeriksanya dengan membandingkan id(item_list)sebelum dan sesudah item_list = [e for e in item_list if e not in ('item', 5)]. Periksa jawaban saya untuk melihat cara mengubah daftar di tempat.
Darkonaut
20
item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove=['item', 5, 'foo']

daftar terakhir setelah menghapus harus sebagai berikut

final_list=[3.14, True]

Kode Baris Tunggal

final_list= list(set(item_list).difference(set(list_to_remove)))

keluarannya adalah sebagai berikut

final_list=[3.14, True]
Aakash Goel
sumber
13
tidak, itu mengocok item dalam daftar. Gunakan hanya jika urutan item tidak menjadi masalah, yang cukup sering terjadi.
pemulung
5
Ini juga akan menghapus duplikat dari daftar. Bukan berarti itu penting untuk daftar contoh
tschale
1
Jawaban ini salah dan dapat menyebabkan bug yang serius, mengapa di-upvot?
omerfarukdogan
1
Ini akan menghapus duplikat! Jawabannya dapat menyebabkan bug serius, jangan gunakan.
user2698178
2

Saya tidak tahu mengapa semua orang lupa menyebutkan kemampuan luar biasa sets dengan python. Anda cukup memasukkan daftar Anda ke dalam satu set dan kemudian menghapus apa pun yang ingin Anda hapus dalam ekspresi sederhana seperti:

>>> item_list = ['item', 5, 'foo', 3.14, True]
>>> item_list = set(item_list) - {'item', 5}
>>> item_list
{True, 3.14, 'foo'}
>>> # you can cast it again in a list-from like so
>>> item_list = list(item_list)
>>> item_list
[True, 3.14, 'foo']
Anwarvic
sumber
6
Tidak menjaga urutan objek sekalipun.
Astrid
Dan juga akan menghapus duplikat yang berpotensi ada di daftar.
kyriakosSt
1

Saya memposting ulang jawaban saya dari sini karena saya melihatnya juga cocok di sini. Ini memungkinkan menghapus beberapa nilai atau menghapus hanya duplikat dari nilai-nilai ini dan mengembalikan daftar baru atau mengubah daftar yang diberikan di tempat.


def removed(items, original_list, only_duplicates=False, inplace=False):
    """By default removes given items from original_list and returns
    a new list. Optionally only removes duplicates of `items` or modifies
    given list in place.
    """
    if not hasattr(items, '__iter__') or isinstance(items, str):
        items = [items]

    if only_duplicates:
        result = []
        for item in original_list:
            if item not in items or item not in result:
                result.append(item)
    else:
        result = [item for item in original_list if item not in items]

    if inplace:
        original_list[:] = result
    else:
        return result

Ekstensi Docstring:

"""
Examples:
---------

    >>>li1 = [1, 2, 3, 4, 4, 5, 5]
    >>>removed(4, li1)
       [1, 2, 3, 5, 5]
    >>>removed((4,5), li1)
       [1, 2, 3]
    >>>removed((4,5), li1, only_duplicates=True)
       [1, 2, 3, 4, 5]

    # remove all duplicates by passing original_list also to `items`.:
    >>>removed(li1, li1, only_duplicates=True)
      [1, 2, 3, 4, 5]

    # inplace:
    >>>removed((4,5), li1, only_duplicates=True, inplace=True)
    >>>li1
        [1, 2, 3, 4, 5]

    >>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
    >>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
    >>>li2
        ['abc', 'def', 'ghi']
"""

Anda harus jelas tentang apa yang sebenarnya ingin Anda lakukan, mengubah daftar yang ada, atau membuat daftar baru dengan item tertentu hilang. Penting untuk membuat perbedaan itu jika Anda memiliki referensi kedua yang menunjuk ke daftar yang ada. Jika sudah, misalnya ...

li1 = [1, 2, 3, 4, 4, 5, 5]
li2 = li1
# then rebind li1 to the new list without the value 4
li1 = removed(4, li1)
# you end up with two separate lists where li2 is still pointing to the 
# original
li2
# [1, 2, 3, 4, 4, 5, 5]
li1
# [1, 2, 3, 5, 5]

Ini mungkin atau mungkin bukan perilaku yang Anda inginkan.

Darkonaut
sumber
1

Anda dapat menggunakan fungsi filterfalse dari modul itertools

Contoh

import random
from itertools import filterfalse

random.seed(42)

data = [random.randrange(5) for _ in range(10)]
clean = [*filterfalse(lambda i: i == 0, data)]
print(f"Remove 0s\n{data=}\n{clean=}\n")


clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1s\n{data=}\n{clean=}")

Keluaran:

Remove 0s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 1, 1, 1, 4, 4]

Remove 0s and 1s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 4, 4]
Vlad Bezden
sumber
0

Tetapi bagaimana jika saya tidak tahu indeks item yang ingin saya hapus?

Saya tidak begitu mengerti mengapa Anda tidak suka .remove tetapi untuk mendapatkan indeks pertama yang sesuai dengan nilai, gunakan .index (value):

ind=item_list.index('item')

lalu hapus nilai yang sesuai:

del item_list.pop[ind]

.index (nilai) mendapatkan kemunculan pertama nilai, dan .remove (nilai) menghapus kemunculan nilai pertama

aless80
sumber
Pertimbangkan untuk menggunakan del item_list[ind]daripada popjika Anda tidak membutuhkan nilai hasil.
kojiro
-1

Anda dapat menggunakan ini -

Misalkan kita punya daftar, l = [1,2,3,4,5]

Kami ingin menghapus dua item terakhir dalam satu pernyataan

del l[3:]

Kami memiliki keluaran:

l = [1,2,3]

Tetap Sederhana

Krishna Singhal
sumber