TypeError: tipe yang tidak dapat ditemukan: 'dict'

175

Bagian kode ini memberi saya kesalahan, unhashable type: dictadakah yang bisa menjelaskan kepada saya apa solusinya?

negids = movie_reviews.fileids('neg')
def word_feats(words):
    return dict([(word, True) for word in words])

negfeats = [(word_feats(movie_reviews.words(fileids=[f])), 'neg') for f in negids]
stopset = set(stopwords.words('english'))

def stopword_filtered_word_feats(words):
    return dict([(word, True) for word in words if word not in stopset])

result=stopword_filtered_word_feats(negfeats)
pengguna1805250
sumber
3
Akan bermanfaat untuk menampilkan laporan kesalahan sehingga kita dapat melihat baris mana yang memiliki masalah ...
drevicko

Jawaban:

248

Anda mencoba menggunakan dictsebagai kunci untuk yang lain dictatau dalam set. Itu tidak berfungsi karena kuncinya harus dapat hashable. Sebagai aturan umum, hanya objek yang tidak dapat diubah (string, integer, float, frozenset, tuple of immutables) yang dapat hashable (meskipun pengecualian dimungkinkan). Jadi ini tidak berhasil:

>>> dict_key = {"a": "b"}
>>> some_dict[dict_key] = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

Untuk menggunakan dikt sebagai kunci, Anda perlu mengubahnya menjadi sesuatu yang mungkin di-hash terlebih dahulu. Jika dikt yang ingin Anda gunakan sebagai kunci hanya terdiri dari nilai-nilai yang tidak dapat diubah, Anda dapat membuat representasi hash untuk itu seperti ini:

>>> key = frozenset(dict_key.items())

Sekarang Anda dapat menggunakan keysebagai kunci di dalam dictatau set:

>>> some_dict[key] = True
>>> some_dict
{frozenset([('a', 'b')]): True}

Tentu saja Anda harus mengulang latihan kapan pun Anda ingin mencari sesuatu menggunakan dikt:

>>> some_dict[dict_key]                     # Doesn't work
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> some_dict[frozenset(dict_key.items())]  # Works
True

Jika dictAnda ingin menggunakan sebagai kunci memiliki nilai-nilai yang sendiri adalah dicts dan / atau daftar, Anda perlu secara rekursif "membekukan" kunci prospektif. Inilah titik awalnya:

def freeze(d):
    if isinstance(d, dict):
        return frozenset((key, freeze(value)) for key, value in d.items())
    elif isinstance(d, list):
        return tuple(freeze(value) for value in d)
    return d
Lauritz V. Thaulow
sumber
2
Terima kasih, ini berfungsi, namun masih mendapatkan kesalahan jika nilainya adalah dict atau daftar (tidak dapat diakses), sekarang saya menggunakan hash (str (my_dict)), berfungsi dengan baik untuk saya.
Steven Du
7
hanya sebuah catatan @StevenDu kamus tidak menjamin pesanan, sehingga str(my_dict)dapat mengembalikan dua string yang berbeda untuk dikte yang sama (atau berbeda, tetapi setara)
K Raphael
1
Untuk mengubah frozenset yang dihasilkan kembali menjadi dict, panggil saja dict(the_frozenset).
pengguna
4
Sepertinya saya yang frozenset(dict_key.items())berpotensi bermasalah karena dua dicts dengan konten yang sama tetapi urutan penyisipan yang berbeda mungkin tidak menghasilkan kunci yang sama. Menambahkan panggilan ke diurutkan () tampaknya berurutan. Misalnya frozenset(sorted(dict_key.items()))Selain itu, frozenset sepertinya pilihan aneh mengingat bahwa set secara eksplisit tidak teratur. Ini mungkin berfungsi dengan baik dalam praktek, tetapi tuple sepertinya pilihan yang lebih logis bagi saya. Saya pergi bersamatuple(sorted(dict_key.items()))
Jason Heiss
Setuju dengan @JasonHeiss
user3732361
6

Solusi yang mungkin adalah menggunakan metode JSON dumps (), sehingga Anda dapat mengonversi kamus ke string ---

import json

a={"a":10, "b":20}
b={"b":20, "a":10}
c = [json.dumps(a), json.dumps(b)]


set(c)
json.dumps(a) in c

Keluaran -

set(['{"a": 10, "b": 20}'])
True
Matteo Boscolo
sumber
2
Seharusnya dumpstidak dump.
Kushan Gunasekera