Como adiciono o conteúdo de um iterável a um conjunto?

Respostas:

228

Você pode adicionar elementos de lista setcomo este:

>>> 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
fonte
2
Apenas olhei novamente para a minha sessão de intérprete e tentei fazer isso, mas achei que ela havia adicionado a lista inteira como um elemento do conjunto devido aos colchetes na representação do conjunto. Eu nunca tinha notado antes que eles são representados assim.
precisa
7
Essa representação permite colá-lo de volta em uma sessão interativa, porque o setconstrutor assume uma iterável como argumento.
Frank Kusters
3
Note-se que a representação é apenas, por exemplo, {1, 2, 3}em Python 3 enquanto era set([1, 2, 3])em Python 2.
Radon Rosborough
40

Para o benefício de qualquer um que possa acreditar, por exemplo, que fazer aset.add()em loop teria desempenho competitivo em relação a fazer aset.update(), aqui está um exemplo de como você pode testar suas crenças rapidamente antes de se tornar público:

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

Parece que o custo por item da abordagem de loop é mais de TRÊS vezes o da updateabordagem.

Usar |= set()custos cerca de 1,5x o que updatefaz, mas metade do que adiciona cada item individual em um loop.

John Machin
fonte
14

Você pode usar a função set () para converter um iterável em um conjunto e, em seguida, usar o operador de atualização de conjunto padrão (| =) para adicionar os valores exclusivos do seu novo conjunto ao existente.

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])
gbc
fonte
5
Usar .updatetem o benefício de que o argumento pode ser iterável - não necessariamente um conjunto - ao contrário do RHS do |=operador em seu exemplo.
Tbot 28/10/10
1
Bom ponto. É apenas uma escolha estética, já que set () pode converter um iterável em um conjunto, mas o número de pressionamentos de tecla é o mesmo.
gbc
Eu nunca vi esse operador antes, vou gostar de usá-lo quando ele aparecer no futuro; obrigado!
eipxen
1
@eipxen: Há |união, &interseção e ^obtenção de elementos que estão em um ou no outro, mas não em ambos. Mas em uma linguagem de tipo dinâmico, onde às vezes é difícil ler o código e conhecer os tipos de objetos voando, sinto-me hesitante em usar esses operadores. Alguém que não os reconhece (ou talvez nem perceba que o Python permite operadores como esses) pode ficar confuso e pensar que algumas operações lógicas ou bit a bit estão acontecendo. Seria bom se esses operadores também trabalhassem em outros
iterables
Executei alguns testes de tempo neste versus .update()e adicione elementos individuais em um loop. Achei que .update()era mais rápido. Adicionei meus resultados a esta resposta existente: stackoverflow.com/a/4046249/901641
Adicionei
4

Apenas uma atualização rápida, horários usando 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)

Os resultados são:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082
Daniel Dubovski
fonte
0

Use a compreensão da lista.

Curto-circuito na criação de iterável usando uma lista, por exemplo :)

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

[Editar: perdeu a parte definida da pergunta]

pyfunc
fonte
1
Não vejo nenhum conjunto? Estou esquecendo de algo?
precisa
-2
for item in items:
   extant_set.add(item)

Para o registro, acho que a afirmação de que "deveria haver uma - e de preferência apenas uma - maneira óbvia de fazê-lo". é falso. Supõe-se que muitas pessoas de espírito técnico fazem, que todo mundo pensa da mesma forma. O que é óbvio para uma pessoa não é tão óbvio para outra.

Eu diria que minha solução proposta é claramente legível e faz o que você pede. Não acredito que haja algum impacto no desempenho envolvido - embora admita que possa estar faltando alguma coisa. Mas, apesar de tudo isso, pode não ser óbvio e preferível a outro desenvolvedor.

jaydel
fonte
Argh! O loop for estando em uma linha como essa está formatando na minha resposta - eu nunca faria isso. Sempre.
Jaydel #
Você está absolutamente correto. Eu editei o post para reparar meu dano. Obrigado :)
jaydel 28/10/10
9
Você está perdendo o ponto que faz um aset.update(iterable)loop na velocidade C e o for item in iterable: aset.add(item)loop na velocidade do Python, com uma pesquisa de método e uma chamada de método (aarrgghh !!) por item.
precisa
1
Desculpe, ele não disse nada sobre desempenho em sua pergunta, então não me preocupei.
21711 jaydel