Yinelenebilir bir öğenin içeriğini bir kümeye nasıl eklerim?


Yanıtlar:


228

Bir unsurlarını ekleyebilir lista setböyle:

>>> foo = set(range(0, 4))
>>> foo
set([0, 1, 2, 3])
>>> foo.update(range(2, 6))
>>> foo
set([0, 1, 2, 3, 4, 5])

2
Tercüman oturumuma tekrar baktım ve bunu gerçekten denedim, ancak setin temsilindeki köşeli parantezler nedeniyle tüm listeyi setin bir öğesi olarak eklediğini düşündüm. Daha önce hiç böyle fark edilmediklerini fark etmemiştim.
Ian Mackinnon

7
Bu temsil, onu etkileşimli bir oturuma geri yapıştırmanıza izin verir, çünkü setyapıcı argümanı olarak bir yinelenebilir.
Frank Kusters

3
{1, 2, 3}set([1, 2, 3])
Temsilin

40

Örneğin, aset.add()bir döngüde yapmanın performansla rekabet edebileceğine inanabilen herkesin yararına, halka aset.update()açılmadan önce inançlarınızı nasıl hızlı bir şekilde test edebileceğinize bir örnek:

>\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

Döngü yaklaşımının öğe başına maliyeti, yaklaşımın ÜÇ katından fazla gibi görünüyor update.

Kullanılması |= set()Ne 1.5x hakkında maliyetlerini updateyapar ama bir döngü yapar içinde, her birini ekleyerek ne yarısında.


14

Bir yinelemeyi bir kümeye dönüştürmek için set () işlevini kullanabilir ve ardından yeni kümenizdeki benzersiz değerleri mevcut kümeye eklemek için standart küme güncelleme işlecini (| =) kullanabilirsiniz.

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])

5
Kullanmak .update, argümanın, örnekteki |=operatörün RHS'sinden farklı olarak, zorunlu olarak bir küme değil - yinelenebilir olması avantajına sahiptir .
tzot

1
İyi bir nokta. Set () bir yinelemeyi bir sete dönüştürebildiği için sadece estetik bir seçimdir, ancak tuş vuruşlarının sayısı aynıdır.
gbc

Bu operatörü daha önce hiç görmedim, gelecekte ortaya çıktığı zaman kullanmaktan zevk alacağım; Teşekkürler!
eipxen

1
@ eipxen: |Birlik, &kavşak ve ^her ikisinde birden bulunmayan ancak ikisinde birden bulunmayan elemanlar almak için var. Ancak, kodu okumak ve etrafta uçan nesnelerin türlerini bilmek bazen zor olan dinamik olarak yazılmış bir dilde, bu operatörleri kullanmaktan çekiniyorum. Onları tanımayan (veya belki de Python'un bu gibi operatörlere izin verdiğinin farkında bile olmayan) biri kafa karıştırılabilir ve bazı garip bitsel veya mantıksal işlemlerin devam ettiğini düşünebilir. Bu operatörlerin başka yinelemeler üzerinde de çalışması iyi olurdu ...
ArtOfWarfare

Buna karşı biraz zaman testi yapın .update()ve bir döngüye tek tek öğeler ekleyin. O Bulunan .update()hızlıydı. Sonuçlarımı şu mevcut cevaba
ekledim

4

Sadece hızlı bir güncelleme, python 3 kullanarak zamanlamalar:

#!/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)

sonuçlar:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082

0

Liste kavrayışı kullanın.

Örneğin bir liste kullanarak yinelenebilir oluşturma kısa devre :)

>>> 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])
>>> 

[Düzenle: sorunun ayarlanan kısmını kaçırdınız]


1
Hiç set görmüyorum? Bir şey mi kaçırıyorum?
Ian Mackinnon

-2
for item in items:
   extant_set.add(item)

Kayıt için, bence "Bir - ve tercihen sadece - bir tane yapmanın açık yolu olmalı" iddiası. sahte. Birçok teknik düşünen insanın yaptığı ve herkesin aynı şekilde düşündüğü varsayımı vardır. Bir insan için açık olan başka bir insan için açık değildir.

Önerdiğim çözümün açıkça okunabilir olduğunu ve ne istediğini yaptığını iddia ediyorum. Bununla ilgili herhangi bir performans isabeti olduğuna inanmıyorum - bir şey eksik olabileceğimi itiraf ediyorum. Ancak tüm bunlara rağmen, başka bir geliştiriciye açık ve tercih edilebilir olmayabilir.


Ahh! Böyle bir satırda for döngüsü cevabım biçimleniyor - bunu asla yapmam. Hiç.
jaydel

Kesinlikle haklısın. Hasarımı onarmak için gönderiyi düzenledim. Thanks :)
jaydel

9
Bir noktayı eksik olduğunu aset.update(iterable)oysa C hızında döngüler for item in iterable: aset.add(item)bir yöntem arama ve yöntem çağrısı (aarrgghh !!) başına öğe ile Python hızında döngüler.
John Machin

1
Üzgünüm, sorusundaki performans hakkında hiçbir şey söylemedi, bu yüzden endişelenmedim.
jaydel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.