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

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.


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

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

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]


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.