Eu tenho uma lista com 15 números e preciso escrever um código que produza todas as 32.768 combinações desses números.
Encontrei algum código (do Google) que aparentemente faz o que estou procurando, mas achei o código bastante opaco e desconfio de usá-lo. Além disso, sinto que deve haver uma solução mais elegante.
A única coisa que me ocorre seria apenas percorrer os números decimais de 1 a 32768 e convertê-los em binários, e usar a representação binária como um filtro para selecionar os números apropriados.
Alguém sabe de uma maneira melhor? Usando map()
, talvez?
python
combinations
Ben
fonte
fonte
product
etc.)Respostas:
Dê uma olhada em itertools.combinations :
Desde 2.6, as pilhas estão incluídas!
fonte
list(itertools.combinations(iterable, r))
r
, isto é, combinações de qualquer subsequência de comprimento de elementos.Essa resposta perdeu um aspecto: o OP solicitou TODAS as combinações ... não apenas as combinações de comprimento "r".
Então você teria que percorrer todos os comprimentos "L":
Ou - se você quiser ficar esnobe (ou torcer o cérebro de quem lê seu código depois de você) - você pode gerar a cadeia de geradores de "combinações ()" e iterar com isso:
fonte
powerset()
função geradora na seção de receitas daitertools
documentação é mais simples, potencialmente usa menos memória e provavelmente é mais rápida que a implementação mostrada aqui.itertools.combinations
preserva a ordem dos itens nas listas que produz. Assim, se a entrada for classificada lexicamente, cada uma das saídas também será.itertools.combinations
gera as combinações de k entre n em ordem lexicográfica, mas nem todas as combinações até k entre n.powerset
gera todas as combinações até k, mas não em ordem lexicográfica, tanto quanto eu a entendo: powerset ([1,2]) -> [(), (1,), (2,), (1, 2)] . Não deveria ser: [(), (1,), (1, 2), (2,)]?Aqui está um one-liner preguiçoso, também usando itertools:
Ideia principal por trás desta resposta: existem 2 ^ N combinações - o mesmo que o número de cadeias binárias de comprimento N. Para cada cadeia binária, você escolhe todos os elementos correspondentes a um "1".
Coisas a considerar:
len(...)
emitems
(solução: seitems
é algo como um iterável como um gerador, transformá-lo em uma lista pela primeira vez comitems=list(_itemsArg)
)items
não seja aleatória (solução alternativa: não fique louco){2,2,1}
e{2,1,1}
serão ambos colapso a{2,1}
(solução alternativa: o usocollections.Counter
como um substituto paraset
, é basicamente um multiset ... embora você pode precisar de usar mais tardetuple(sorted(Counter(...).elements()))
se você precisa que ele seja Hashable)Demo
fonte
Nos comentários sob a resposta altamente votada por @Dan H, é mencionada a
powerset()
receita naitertools
documentação - incluindo uma do próprio Dan . No entanto , até agora ninguém postou como resposta. Como é provavelmente uma das melhores, se não a melhor, para o problema - e com um pouco de incentivo de outro comentarista, é mostrado abaixo. A função produz todas as combinações exclusivas dos elementos da lista de todos os comprimentos possíveis (incluindo aqueles que contêm zero e todos os elementos).Nota : Se o, sutilmente diferente, o objetivo é obter apenas as combinações de elementos únicos, altere a linha
s = list(iterable)
paras = list(set(iterable))
eliminar quaisquer elementos duplicados. Independentemente disso, o fato deiterable
finalmente ser transformado em umlist
meio funcionará com geradores (ao contrário de várias das outras respostas).Resultado:
fonte
list()
conversão?Aqui está um usando recursão:
fonte
new_data = copy.copy(data)
- esta linha é redundante, tanto quanto eu vejo, ele não influencia em nadaEssa linha fornece todas as combinações (entre
0
en
itens, se a lista / conjunto original contivern
elementos distintos) e usa o método nativoitertools.combinations
:Python 2
Python 3
A saída será:
Experimente online:
http://ideone.com/COghfX
fonte
['b', 'a']
.TypeError: can only concatenate list (not "map") to list
Eu concordo com Dan H que Ben realmente pediu todas as combinações.
itertools.combinations()
não fornece todas as combinações.Outra questão é que, se a entrada iterável for grande, talvez seja melhor retornar um gerador em vez de tudo em uma lista:
fonte
Essa é uma abordagem que pode ser facilmente transferida para todas as linguagens de programação que suportam recursão (sem ferramentas, sem rendimento, sem compreensão de lista) :
fonte
Você pode gerar todas as combinações de uma lista em python usando este código simples
O resultado seria:
fonte
Eu pensei em adicionar essa função para aqueles que procuram uma resposta sem importar ferramentas de ferramentas ou quaisquer outras bibliotecas extras.
Uso simples do gerador de rendimento:
Exemplo de saída do uso acima:
fonte
Aqui está mais uma solução (one-liner), envolvendo o uso da
itertools.combinations
função, mas aqui usamos uma compreensão de lista dupla (em oposição a um loop ou soma for):Demo:
fonte
resultado
fonte
Abaixo está uma "resposta recursiva padrão", semelhante à outra resposta semelhante https://stackoverflow.com/a/23743696/711085 . (Realisticamente, não precisamos nos preocupar em ficar sem espaço na pilha, pois não há como processar todas as permutações do N!).
Ele visita todos os elementos por sua vez e o pega ou sai (podemos ver diretamente a cardinalidade 2 ^ N deste algoritmo).
Demo:
fonte
Usando a compreensão da lista:
A saída seria:
fonte
Este código emprega um algoritmo simples com listas aninhadas ...
fonte
""
).Sei que é muito mais prático usar as ferramentas para obter todas as combinações, mas você pode conseguir isso em parte apenas com compreensão de lista, se assim o desejar, desde que você deseje codificar muito
Para combinações de dois pares:
E, para combinações de três pares, é tão fácil quanto isto:
O resultado é idêntico ao uso itertools.combinations:
fonte
Sem usar itertools:
fonte
Aqui estão duas implementações de
itertools.combinations
Um que retorna uma lista
Um retorna um gerador
Observe que é aconselhável fornecer uma função auxiliar àqueles, porque o argumento de prefpend é estático e não é alterado a cada chamada
Este é um caso muito superficial, mas é melhor prevenir do que remediar
fonte
Que tal isso .. usou uma string em vez de list, mas a mesma coisa .. string pode ser tratada como uma lista em Python:
fonte
Combinação de itertools
obrigado
fonte
Sem
itertools
no Python 3 você poderia fazer algo assim:onde inicialmente
carry = "".
fonte
3 funções:
fonte
Esta é a minha implementação
fonte
Você também pode usar a função powerset do excelente
more_itertools
pacote.Também podemos verificar se ele atende aos requisitos do OP
fonte
fonte
Se alguém está procurando uma lista invertida, como eu:
fonte
fonte