Pertanyaan Hapus elemen dari kamus


Apakah ada cara untuk menghapus item dari kamus dengan Python?

Selain itu, bagaimana cara menghapus item dari kamus untuk mengembalikan salinan (yaitu, tidak memodifikasi dokumen asli)?


842
2018-04-30 21:20


asal


Jawaban:


Itu del pernyataan menghapus elemen:

del d[key]

Namun, ini mem-mutasi kamus yang ada sehingga isi kamus berubah untuk orang lain yang memiliki referensi ke instance yang sama. Untuk mengembalikan a baru kamus, buat salinan kamus:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

Itu dict() konstruktor membuat salinan dangkal. Untuk membuat salinan yang mendalam, lihat copy modul.


Perhatikan bahwa membuat salinan untuk setiap dikte del/ tugas / dll. berarti Anda akan dari waktu konstan ke waktu linier, dan juga menggunakan ruang linear. Untuk diktat kecil, ini bukan masalah. Tetapi jika Anda berencana untuk membuat banyak salinan dicts besar, Anda mungkin menginginkan struktur data yang berbeda, seperti HAMT (seperti yang dijelaskan di jawaban ini).


1184
2018-04-30 21:25



pop bermutasi kamus.

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}

Jika Anda ingin menyimpan aslinya, Anda tinggal menyalinnya.


130
2018-03-21 16:22



Saya pikir solusi Anda adalah cara terbaik untuk melakukannya. Tetapi jika Anda ingin solusi lain, Anda dapat membuat kamus baru dengan menggunakan kunci dari kamus lama tanpa menyertakan kunci yang ditentukan, seperti ini:

>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}

55
2018-04-30 21:26



Itu pernyataan del adalah apa yang Anda cari. Jika Anda memiliki kamus bernama foo dengan kunci yang disebut 'bar', Anda dapat menghapus 'bar' dari foo seperti ini:

del foo['bar']

Perhatikan bahwa ini secara permanen mengubah kamus yang sedang dioperasikan. Jika Anda ingin menyimpan kamus aslinya, Anda harus membuat salinan sebelumnya:

>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}

Itu dict panggilan membuat salinan yang dangkal. Jika Anda ingin menyalin dalam, gunakan copy.deepcopy.

Berikut ini metode yang dapat Anda salin & tempel, untuk kenyamanan Anda:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy

47
2018-04-30 21:23



d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

Hasil: d = {1: 2, '2': 3}


16
2018-04-30 21:24



Ada banyak jawaban yang bagus, tetapi saya ingin menekankan satu hal.

Anda dapat menggunakan keduanya dict.pop() metode dan lebih umum del pernyataan untuk menghapus item dari kamus. Keduanya memutasi kamus aslinya, jadi Anda perlu membuat salinannya (lihat detail di bawah).

Dan keduanya akan meningkatkan KeyError jika kunci yang Anda berikan kepada mereka tidak ada dalam kamus:

key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove]  # Raises `KeyError: 'c'`

dan

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove)  # Raises `KeyError: 'c'`

Anda harus mengurus ini:

dengan menangkap pengecualian:

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    del d[key_to_remove]
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

dan

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    d.pop(key_to_remove)
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

dengan melakukan pemeriksaan:

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    del d[key_to_remove]

dan

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    d.pop(key_to_remove)

tetapi dengan pop() ada juga cara yang jauh lebih ringkas - berikan nilai pengembalian default:

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None)  # No `KeyError` here

Kecuali Anda gunakan pop() untuk mendapatkan nilai kunci yang dihapus, Anda dapat memberikan apa pun, tidak perlu None. Meskipun mungkin itu menggunakan del dengan in periksa adalah sedikit lebih cepat karena pop() menjadi fungsi dengan komplikasinya sendiri yang menyebabkan overhead. Biasanya tidak demikian, jadi pop() dengan nilai default sudah cukup baik.


Untuk pertanyaan utama, Anda harus membuat salinan kamus Anda, untuk menyimpan kamus asli dan memiliki yang baru tanpa kunci dihapus.

Beberapa orang lain di sini menyarankan membuat salinan penuh (dalam) dengan copy.deepcopy(), yang mungkin berlebihan, salinan "normal" (dangkal), menggunakan copy.copy() atau dict.copy(), mungkin sudah cukup. Kamus menyimpan referensi ke objek sebagai nilai kunci. Jadi ketika Anda menghapus kunci dari kamus referensi ini dihapus, bukan objek yang direferensikan. Objek itu sendiri dapat dihapus kemudian secara otomatis oleh garbage collector, jika tidak ada referensi lain untuk itu di dalam memori. Membuat salinan yang mendalam membutuhkan lebih banyak perhitungan dibandingkan dengan salinan dangkal, sehingga mengurangi kinerja kode dengan membuat salinan, membuang-buang memori dan menyediakan lebih banyak pekerjaan ke GC, kadang-kadang salinan dangkal sudah cukup.

Namun, jika Anda memiliki objek yang dapat berubah sebagai nilai kamus dan berencana untuk mengubahnya nanti dalam kamus yang dikembalikan tanpa kunci, Anda harus membuat salinan yang mendalam.

Dengan salinan dangkal:

def get_dict_wo_key(dictionary, key):
    """Returns a **shallow** copy of the dictionary without a key."""
    _dict = dictionary.copy()
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

Dengan salinan mendalam:

from copy import deepcopy


def get_dict_wo_key(dictionary, key):
    """Returns a **deep** copy of the dictionary without a key."""
    _dict = deepcopy(dictionary)
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

16
2017-09-21 19:52



Cukup hubungi del d ['key'].

Namun, dalam produksi, itu selalu merupakan praktik yang baik untuk memeriksa apakah 'kunci' ada di d.

if 'key' in d:
    del d['key']

12
2018-03-02 13:39



Tidak, tidak ada jalan lain selain itu

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

Namun, sering membuat salinan kamus hanya sedikit diubah mungkin bukan ide yang baik karena akan menghasilkan tuntutan memori yang relatif besar. Biasanya lebih baik untuk log kamus lama (jika diperlukan) dan kemudian memodifikasinya.


6
2018-04-30 21:27



>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

ini tidak melakukan penanganan kesalahan, ini mengasumsikan bahwa kunci ada di dikt, Anda mungkin ingin memeriksa yang pertama dan raise jika tidak


5
2018-04-30 21:26



... bagaimana cara menghapus item dari kamus untuk mengembalikan salinan (yaitu, tidak memodifikasi dokumen asli)?

SEBUAH dict adalah struktur data yang salah untuk digunakan untuk ini.

Tentu, menyalin dict dan popping dari karya copy, dan begitu juga membangun dikt baru dengan pemahaman, tetapi semua yang menyalin membutuhkan waktu - Anda telah menggantikan operasi waktu-konstan dengan waktu linear. Dan semua salinan itu hidup sekaligus mengambil ruang — ruang linear per salinan.

Struktur data lainnya, seperti hash array yang dipetakan coba, dirancang untuk persis seperti ini kasus penggunaan: menambahkan atau menghapus elemen mengembalikan salinan dalam waktu logaritmik, berbagi sebagian besar penyimpanannya dengan yang asli.1

Tentu saja ada beberapa kerugian. Kinerja adalah logaritmik daripada konstan (meskipun dengan basis besar, biasanya 32-128). Dan, sementara Anda dapat membuat API yang tidak bermutasi identik dengan dict, API "bermutasi" jelas berbeda. Dan, yang paling penting, tidak ada baterai HAMT yang disertakan dengan Python.2

Itu pyrsistent perpustakaan adalah implementasi yang cukup padat dari dict-replacements berbasis-HAMT (dan berbagai jenis lainnya) untuk Python. Bahkan itu bagus API evolver untuk mem-porting kode mutasi yang ada ke kode gigih semulus mungkin. Tetapi jika Anda ingin bersikap eksplisit tentang mengembalikan salinan alih-alih bermutasi, Anda cukup menggunakannya seperti ini:

>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})

Bahwa d3 = d1.remove('a') adalah persis apa yang ditanyakan pertanyaan itu.

Jika Anda punya struktur data yang bisa berubah seperti dict dan list tertanam dalam pmap, Anda masih memiliki masalah aliasing — Anda hanya dapat memperbaikinya dengan terus berubah sepanjang perjalanan, embedding pmaps dan pvectors.


1. HAMT juga telah menjadi populer dalam bahasa seperti Scala, Clojure, Haskell karena mereka bermain sangat baik dengan pemrograman bebas-lock dan memori transaksional perangkat lunak, tetapi tidak satupun dari keduanya sangat relevan dengan Python.

2. Sebenarnya, di sana aku s sebuah HAMT di stdlib, digunakan dalam implementasi contextvars. PEP menarik sebelumnya menjelaskan mengapa. Tapi ini adalah detail implementasi tersembunyi dari perpustakaan, bukan tipe koleksi publik.


5
2018-05-15 01:19



Di sini pendekatan desain tingkat atas:

def eraseElement(d,k):
    if isinstance(d, dict):
        if k in d:
            d.pop(k)
            print(d)
        else:
            print("Cannot find matching key")
    else:
        print("Not able to delete")


exp = {'A':34, 'B':55, 'C':87}
eraseElement(exp, 'C')

Saya menyampaikan kamus dan kunci yang saya inginkan ke dalam fungsi saya, memvalidasi apakah itu kamus dan jika kuncinya tidak apa-apa, dan jika keduanya ada, hapus nilai dari kamus dan cetak kiri-overs.

Keluaran: {'B': 55, 'A': 34}

Semoga itu membantu!


4
2018-01-25 15:12