Tambahkan daftar untuk ditetapkan?

242

Diuji menggunakan interpreter Python 2.6:

>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> a.add(l)
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    a.add(l)
TypeError: list objects are unhashable

Saya pikir saya tidak dapat menambahkan daftar ke set karena tidak ada cara Python dapat mengatakan jika saya telah menambahkan daftar yang sama dua kali. Apakah ada solusinya?

EDIT: Saya ingin menambahkan daftar itu sendiri, bukan elemennya.

Adam Matan
sumber
2
Apakah Anda ingin menambahkan daftar ke set atau item dalam daftar?
pkit
Daftar itu sendiri - Saya ingin memiliki satu set daftar.
Adam Matan
Tampaknya jawaban yang paling cocok adalah yang diremehkan, menyarankan menggunakan aSet.add (id (lst)) sebelum menambahkan lst itu sendiri ke beberapa daftar / antrian / etc, untuk memastikan bahwa Anda melakukannya. Anda harus mempertimbangkan kembali jawaban yang diterima.
Rustam A.

Jawaban:

187

Anda tidak dapat menambahkan daftar ke set karena daftar bisa berubah, artinya Anda dapat mengubah konten daftar setelah menambahkannya ke set.

Namun Anda dapat menambahkan tupel ke set, karena Anda tidak dapat mengubah isi tupel:

>>> a.add(('f', 'g'))
>>> print a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])

Sunting : beberapa penjelasan: Dokumentasi mendefinisikan setsebagai kumpulan objek hashable berbeda yang tidak berurutan. Objek harus hashable sehingga menemukan, menambah dan menghapus elemen dapat dilakukan lebih cepat daripada melihat setiap elemen individu setiap kali Anda melakukan operasi ini. Algoritma spesifik yang digunakan dijelaskan dalam artikel Wikipedia . Algoritma hashing Python dijelaskan pada effbot.org dan __hash__fungsi python dalam referensi python .

Beberapa fakta:

  • Setel elemen serta kunci kamus harus dapat di hashable
  • Beberapa tipe data yang tidak dapat dihancurkan:
    • list: gunakan tuplesaja
    • set: gunakan frozensetsaja
    • dict: tidak memiliki mitra resmi, tetapi ada beberapa resep
  • Instance objek hashable secara default dengan setiap instance memiliki hash unik. Anda bisa mengganti perilaku ini seperti yang dijelaskan dalam referensi python.
Otto Allmendinger
sumber
6
Dan jika Anda ingin menambahkan satu set ke set, gunakan frozenset.
FogleBird
4
collections.namedtuplemungkin dianggap sebagai mitra "resmi" dari dict.
SilentGhost
1
@ Wahnfrieden: yaitu menambahkan isi set, bukan set itu sendiri.
Otto Allmendinger
@ aehlke: Tidak, itu menambahkan elemen set ke set pertama, tapi kita berbicara tentang menambahkan set sebagai elemen set pertama.
Jeff Learman
578

Gunakan set.update()atau|=

>>> a = set('abc')
>>> l = ['d', 'e']
>>> a.update(l)
>>> a
{'e', 'b', 'c', 'd', 'a'}

>>> l = ['f', 'g']
>>> a |= set(l)
>>> a
{'e', 'b', 'f', 'c', 'd', 'g', 'a'}

sunting: Jika Anda ingin menambahkan daftar itu sendiri dan bukan anggotanya, maka Anda harus menggunakan tuple, sayangnya. Tetapkan anggota harus hashable .

aehlke
sumber
set.update () menambahkan daftar ke set, benar? untuk apa pipa sama dengan operator?
FistOfFury
Sehubungan dengan set, |operator mengimplementasikan operasi set union . Baik |=operator dan set.update()metode menerapkan operasi itu di tempat dan secara efektif bersinonim. Jadi, set_a |= set_bdapat dianggap sebagai gula sintaksis untuk keduanya set_a.update(set_b) dan set_a = set_a | set_b (kecuali bahwa dalam kasus yang terakhir, set_aobjek yang sama digunakan kembali alih-alih dipindahkan). </ahem>
Cecil Curry
76

Untuk menambahkan elemen daftar ke set , gunakanupdate

Dari https://docs.python.org/2/library/sets.html

s.update (t): mengembalikan set s dengan elemen yang ditambahkan dari t

Misalnya

>>> s = set([1, 2])
>>> l = [3, 4]
>>> s.update(l)
>>> s
{1, 2, 3, 4}

Jika Anda ingin menambahkan seluruh daftar sebagai elemen tunggal ke set, Anda tidak bisa karena daftar tidak dapat hashable. Anda bisa menambahkan tuple, mis s.add(tuple(l)). Lihat juga TypeError: tipe yang tidak dapat diakses: 'daftar' saat menggunakan fungsi set bawaan untuk informasi lebih lanjut tentang itu.

JDiMatteo
sumber
40

Semoga ini membantu:

>>> seta = set('1234')
>>> listb = ['a','b','c']
>>> seta.union(listb)
set(['a', 'c', 'b', '1', '3', '2', '4'])
>>> seta
set(['1', '3', '2', '4'])
>>> seta = seta.union(listb)
>>> seta
set(['a', 'c', 'b', '1', '3', '2', '4'])
alva
sumber
15

Mohon perhatikan fungsinya set.update(). Dokumentasi mengatakan:

Perbarui satu set dengan penyatuan itu sendiri dan orang lain.

terong
sumber
5
Ini tidak menjawab pertanyaan (karena OP ingin menambahkan daftar itu sendiri ke set) tetapi itu adalah jawaban yang saya butuhkan ketika Google membawa saya ke sini :-)
tom stratton
1
Yah, sepertinya jawaban yang paling relevan untuk pertanyaan saya ... misalnya, jika b = set ([1]), b.update ([7,25]) akan memberikan b nilai berikut: set ([ 1, 25, 7]) ---> Bukankah itu yang kita cari di sini?
Louis LC
8

daftar objek tidak dapat diakses . Anda mungkin ingin mengubahnya menjadi tupel.

SilentGhost
sumber
5

Set tidak dapat memiliki elemen / anggota yang dapat diubah (dapat diubah). Daftar, yang bisa berubah, tidak bisa menjadi anggota set.

Karena set dapat berubah, Anda tidak dapat memiliki satu set set! Anda dapat memiliki satu set frozenset.

(Jenis "persyaratan mutabilitas" yang sama berlaku untuk kunci-kunci dict.)

Jawaban lain sudah memberi Anda kode, saya harap ini memberikan sedikit wawasan. Saya berharap Alex Martelli akan menjawab dengan lebih detail.

pengguna135331
sumber
4

Anda ingin menambahkan tupel, bukan daftar:

>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> t = tuple(l)
>>> t
('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])

Jika Anda memiliki daftar, Anda dapat mengonversi ke tuple, seperti yang ditunjukkan di atas. Sebuah tuple tidak dapat diubah, sehingga dapat ditambahkan ke set.

hughdbrown
sumber
4

Saya menemukan saya perlu melakukan sesuatu yang serupa hari ini. Algoritma tahu kapan itu membuat daftar baru yang perlu ditambahkan ke set, tetapi tidak ketika itu akan selesai beroperasi pada daftar.

Pokoknya, perilaku yang saya inginkan adalah untuk menggunakan iddaripada mengatur hash. Karena itu saya menemukan mydict[id(mylist)] = mylistalih-alih myset.add(mylist)menawarkan perilaku yang saya inginkan.

Bukit pasir
sumber
3

Anda akan ingin menggunakan tuple, yang hashable (Anda tidak bisa hash objek yang bisa berubah seperti daftar).

>>> a = set("abcde")
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> t = ('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Nuh
sumber
2

Beginilah biasanya saya melakukannya:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
Kashif
sumber
-4

Ini harus dilakukan:

set(tuple(i) for i in L)
WQS
sumber