Bagaimana cara menambahkan konten iterable ke set?

Jawaban:

228

Anda dapat menambahkan elemen a listke setseperti ini:

>>> foo = set(range(0, 4))
>>> foo
set([0, 1, 2, 3])
>>> foo.update(range(2, 6))
>>> foo
set([0, 1, 2, 3, 4, 5])
SingleNegationElimination
sumber
2
Hanya melihat kembali pada sesi juru bahasa saya dan saya benar-benar mencoba ini, tetapi berpikir bahwa itu telah menambahkan seluruh daftar sebagai elemen dari set karena tanda kurung siku dalam representasi set. Saya belum pernah memperhatikan bahwa mereka diwakili seperti itu.
Ian Mackinnon
7
Representasi itu memungkinkan Anda untuk menempelkannya kembali di sesi interaktif, karena setkonstruktor mengambil iterable sebagai argumennya.
Frank Kusters
3
Perhatikan bahwa representasi hanya misalnya {1, 2, 3}dalam Python 3 sedangkan itu set([1, 2, 3])dalam Python 2.
Radon Rosborough
40

Untuk kepentingan siapa pun yang mungkin percaya misalnya bahwa melakukan aset.add()dalam satu lingkaran akan memiliki kinerja yang kompetitif dengan melakukan aset.update(), berikut adalah contoh bagaimana Anda dapat menguji keyakinan Anda dengan cepat sebelum go public:

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 294 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 950 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 458 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 598 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 1.89 msec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 891 usec per loop

Sepertinya biaya per item dari pendekatan loop lebih dari TIGA kali lipat dari updatependekatan.

Menggunakan |= set()biaya sekitar 1,5x apa yang updatedilakukan tetapi setengah dari apa yang ditambahkan setiap item dalam satu lingkaran tidak.

John Machin
sumber
14

Anda dapat menggunakan fungsi set () untuk mengubah iterable menjadi set, dan kemudian menggunakan operator pembaruan set standar (| =) untuk menambahkan nilai unik dari set baru Anda ke yang sudah ada.

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])
gbc
sumber
5
Menggunakan .updatememiliki manfaat bahwa argumennya dapat diubah-ubah — tidak harus merupakan himpunan — tidak seperti RHS |=operator dalam contoh Anda.
tzot
1
Poin yang bagus. Ini hanya pilihan estetika karena set () dapat mengubah iterable menjadi set, tetapi jumlah penekanan tombolnya sama.
gbc
Saya belum pernah melihat operator itu sebelumnya, saya akan menikmati menggunakannya ketika itu muncul di masa depan; Terima kasih!
eipxen
1
@ Eipxen: Ada |untuk persatuan, &untuk persimpangan, dan ^untuk mendapatkan elemen yang ada di satu atau yang lain tetapi tidak keduanya. Tetapi dalam bahasa yang diketik secara dinamis di mana kadang-kadang sulit untuk membaca kode dan mengetahui jenis benda yang terbang di sekitar, saya merasa ragu untuk menggunakan operator ini. Seseorang yang tidak mengenalinya (atau mungkin bahkan tidak menyadari bahwa Python memungkinkan untuk operator seperti ini) dapat bingung dan berpikir beberapa operasi aneh bitwise atau logis sedang terjadi. Akan lebih baik jika operator ini bekerja pada iterables lainnya juga ...
ArtOfWarfare
Menjalankan beberapa tes waktu pada ini versus .update()dan menambahkan elemen individual dalam satu lingkaran. Menemukan .update()itu lebih cepat. Saya menambahkan hasil saya ke jawaban yang ada ini: stackoverflow.com/a/4046249/901641
ArtOfWarfare
4

Hanya pembaruan cepat, timing menggunakan python 3:

#!/usr/local/bin python3
from timeit import Timer

a = set(range(1, 100000))
b = list(range(50000, 150000))

def one_by_one(s, l):
    for i in l:
        s.add(i)    

def cast_to_list_and_back(s, l):
    s = set(list(s) + l)

def update_set(s,l):
    s.update(l)

hasilnya adalah:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082
Daniel Dubovski
sumber
0

Gunakan pemahaman daftar.

Hubungan pendek pembuatan iterable menggunakan daftar misalnya :)

>>> x = [1, 2, 3, 4]
>>> 
>>> k = x.__iter__()
>>> k
<listiterator object at 0x100517490>
>>> l = [y for y in k]
>>> l
[1, 2, 3, 4]
>>> 
>>> z = Set([1,2])
>>> z.update(l)
>>> z
set([1, 2, 3, 4])
>>> 

[Sunting: merindukan bagian set pertanyaan]

pyfunc
sumber
1
Saya tidak melihat set? Apakah saya melewatkan sesuatu?
Ian Mackinnon
-2
for item in items:
   extant_set.add(item)

Sebagai catatan, saya pikir pernyataan bahwa "Harus ada satu - dan lebih disukai hanya satu - cara yang jelas untuk melakukannya." adalah palsu. Itu membuat asumsi bahwa banyak orang berpikiran teknis membuat, bahwa semua orang berpikir sama. Apa yang jelas bagi satu orang tidak begitu jelas bagi orang lain.

Saya berpendapat bahwa solusi yang saya usulkan jelas dapat dibaca, dan melakukan apa yang Anda minta. Saya tidak percaya ada hit kinerja yang terlibat dengannya - meskipun saya akui saya mungkin kehilangan sesuatu. Namun terlepas dari semua itu, mungkin tidak jelas dan lebih disukai daripada pengembang lain.

jaydel
sumber
Argh! Untuk loop berada di satu baris seperti itu memformat dalam jawaban saya - saya tidak akan pernah melakukan itu. Pernah.
jaydel
Anda benar sekali. Saya mengedit posting untuk memperbaiki kerusakan saya. Terima kasih :)
jaydel
9
Anda kehilangan titik yang aset.update(iterable)loop pada kecepatan C sedangkan for item in iterable: aset.add(item)loop pada kecepatan Python, dengan pencarian metode dan pemanggilan metode (aarrgghh !!) per item.
John Machin
1
Maaf, dia tidak mengatakan apa-apa tentang kinerja dalam pertanyaannya, jadi saya tidak khawatir tentang itu.
jaydel