Che cos'è lo "one [...] obvious way" per aggiungere tutti gli elementi di un iterabile a uno esistente set
?Python: come aggiungere il contenuto di un iterabile a un set?
risposta
dal set, vuoi dire set
?
>>> foo = set(range(0, 4))
>>> foo
set([0, 1, 2, 3])
>>> foo.update(range(2, 6))
>>> foo
set([0, 1, 2, 3, 4, 5])
mi piace questo modo:
set = [item for item in items]
@dolma, io non voglio creare * * un nuovo set, ma aggiungere a un set esistente. Scusa se non era chiaro; Ho modificato la domanda per chiarire. –
@dolma, inoltre, (a) puoi fare 's = set (items)' e (b) il tuo esempio ridefinisce un built-in :) –
quindi puoi semplicemente fare 'set.extend ([item per item in items ]) ', Immagino ... – dolma33
Usa di lista.
corto circuito la creazione di iterabile usando una lista ad esempio :)
>>> 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])
>>>
[Edit: mancava la parte insieme di domanda]
Non vedo nessun set? Mi sto perdendo qualcosa? –
@Ian Mackinnon: Aah! Ha perso completamente quel punto. Grazie. – pyfunc
for item in items:
extant_set.add(item)
Per la cronaca, credo che l'affermazione che "Ci dovrebbe essere tra-- e, preferibilmente, un solo modo --obvious per farlo." è fasullo. Presuppone che molte persone con idee tecniche creino, che tutti la pensano allo stesso modo. Ciò che è ovvio per una persona non è così ovvio per un altro.
Direi che la mia soluzione proposta è chiaramente leggibile e fa quello che chiedi. Non credo che ci siano dei successi nelle performance, anche se ammetto che potrei mancare qualcosa. Ma nonostante tutto, potrebbe non essere ovvio e preferibile a un altro sviluppatore.
Imposta hanno il metodo add troppo:
>>> s=set([1,2,3,4])
>>> for n in range(10):
s.add(n)
>>> s
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
È possibile utilizzare la funzione set() per convertire un iterabile in un set, e quindi utilizzare operatore di aggiornamento insieme standard (| =) per aggiungere i valori univoci dal tuo nuovo set a quello esistente.
>>> a = { 1, 2, 3 }
>>> b = (3, 4, 5)
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])
L'uso di '.update' ha il vantaggio che l'argomento può essere qualsiasi iterabile, non necessariamente un set, a differenza dell'RHS dell'operatore' | = 'nell'esempio. – tzot
Buon punto. È solo una scelta estetica dato che set() può convertire un iterabile in un set, ma il numero di sequenze di tasti è lo stesso. – gbc
Non l'ho mai visto prima, mi divertirò a usarlo quando verrà visualizzato in futuro; Grazie! – eipxen
Per il beneficio di chiunque possa credere ad es. che facendo aset.add()
in un ciclo avrebbe prestazioni competitive con il fare aset.update()
, ecco un esempio di come è possibile testare le vostre convinzioni in fretta prima di andare pubblico:
>\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
Sembra che il costo per punto di un approccio ciclo è più di tre volte quello dell'approccio update
.
L'utilizzo di |= set()
costa circa 1,5 volte il valore di update
ma metà di ciò che aggiunge ogni singolo elemento in un ciclo.
Solo un rapido aggiornamento, timing utilizzando 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)
risultati sono:
one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082
Sì, non mi aspettavo che fosse ambiguo, ma sembra che sia :) L'aggiornamento è proprio la cosa. Grazie! –
Ho appena ripensato alla mia sessione di interprete e in realtà l'ho provato, ma ho pensato che aveva aggiunto l'intera lista come un elemento del set a causa delle parentesi quadre nella rappresentazione del set. Non avevo mai notato prima che fossero rappresentati così. –
Questa rappresentazione consente di incollarla di nuovo in una sessione interattiva, perché il costruttore 'set' prende un argomento iterabile come argomento. –