web-dev-qa-db-fra.com

Python: comment ajouter le contenu d'un itérable à un ensemble?

Quelle est la "une [...] [[]] méthode évidente" d'ajouter tous les éléments d'un itératif à un set existant?

139
Ian Mackinnon

par jeu, voulez-vous 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])
193

Pour le bénéfice de quiconque pourrait croire par exemple pour que aset.add() dans une boucle ait des performances concurrentielles avec aset.update(), voici un exemple de la façon dont vous pouvez tester vos croyances rapidement avant de devenir 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

On dirait que le coût par élément de l'approche en boucle est TROIS fois supérieur à celui de l'approche update.

Utiliser |= set() coûte environ 1,5 fois plus que ce que update fait, mais la moitié de ce que l’ajout de chaque élément individuel dans une boucle coûte.

34
John Machin

Vous pouvez utiliser la fonction set () pour convertir un itérable en un ensemble, puis utiliser l'opérateur de mise à jour d'un ensemble standard (| =) pour ajouter les valeurs uniques de votre nouvel ensemble à celui existant.

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

Juste une mise à jour rapide, les timings utilisant 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)

les résultats sont:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082
2
Daniel Dubovski

tiliser la compréhension de la liste.

Court-circuiter la création de iterable en utilisant une liste par exemple :)

>>> 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: raté la partie définie de la question]

0
pyfunc