J'ai une liste avec 15 chiffres et j'ai besoin d'écrire du code qui produit les 32 768 combinaisons de ces nombres.
J'ai trouvé du code (par Google) qui fait apparemment ce que je recherche, mais j'ai trouvé le code assez opaque et je me méfie de l'utiliser. De plus, j'ai le sentiment qu'il doit y avoir une solution plus élégante.
La seule chose qui me vient à l'esprit serait de parcourir simplement les entiers décimaux 1–32768 et de les convertir en binaire, et d'utiliser la représentation binaire comme filtre pour sélectionner les nombres appropriés.
Quelqu'un connaît-il un meilleur moyen? À l'aide map()
, peut-être?
product
, etc.)Réponses:
Jetez un œil à itertools.combinations :
Depuis 2.6, les piles sont incluses!
la source
list(itertools.combinations(iterable, r))
r
, c'est-à-dire des combinaisons de sous-séquences de n'importe quelle longueur d'éléments.Cette réponse a manqué un aspect: le PO a demandé TOUTES les combinaisons ... pas seulement les combinaisons de longueur "r".
Il vous faudrait donc soit parcourir toutes les longueurs "L":
Ou - si vous voulez devenir fou (ou fléchir le cerveau de celui qui lit votre code après vous) - vous pouvez générer la chaîne de générateurs "combinaisons ()", et itérer à travers cela:
la source
powerset()
fonction de générateur dans la section des recettes de laitertools
documentation est plus simple, utilise potentiellement moins de mémoire et est probablement plus rapide que l'implémentation présentée ici.itertools.combinations
l'ordre des articles est préservé dans les listes qu'il génère. Ainsi, si l'entrée est triée lexicalement, alors chacune des sorties le sera également.itertools.combinations
génère les combinaisons de k parmi n dans l'ordre lexicographique, mais pas toutes les combinaisons jusqu'à k parmi n.powerset
génère toutes les combinaisons jusqu'à k, mais pas dans l'ordre lexicographique pour autant que je le comprends: powerset ([1,2]) -> [(), (1,), (2,), (1, 2)] . Cela ne devrait-il pas être: [(), (1,), (1, 2), (2,)]?Voici un one-liner paresseux, utilisant également itertools:
Idée principale derrière cette réponse: il y a 2 ^ N combinaisons - identiques au nombre de chaînes binaires de longueur N. Pour chaque chaîne binaire, vous choisissez tous les éléments correspondant à un "1".
Choses à considérer:
len(...)
suritems
(solution de contournement: siitems
est quelque chose comme un itérables comme un générateur, la transformer en une première liste avecitems=list(_itemsArg)
)items
ne soit pas aléatoire (solution de contournement: ne soyez pas fou){2,2,1}
et{2,1,1}
sera à la fois à l' effondrement{2,1}
(solution de contournement: l' utilisationcollections.Counter
en remplacement sans rendez- vous pourset
, il est fondamentalement un multiset ... si vous devrez peut - être utiliser plus tardtuple(sorted(Counter(...).elements()))
si vous avez besoin d'être hashable)Démo
la source
Dans les commentaires sous la réponse très appréciée de @Dan H, il est fait mention de la
powerset()
recette dans laitertools
documentation, y compris celle de Dan lui-même . Cependant , jusqu'à présent, personne ne l'a posté comme réponse. Étant donné que c'est probablement l'une des meilleures, sinon la meilleure approche du problème - et étant donné un peu d'encouragement d'un autre intervenant, c'est indiqué ci-dessous. La fonction produit toutes les combinaisons uniques des éléments de liste de toutes les longueurs possibles (y compris celles contenant zéro et tous les éléments).Remarque : Si le, subtilement différent, le but est d'obtenir que des combinaisons d'éléments uniques, changer la ligne
s = list(iterable)
às = list(set(iterable))
éliminer tous les éléments en double. Quoi qu'il en soit, le fait que leiterable
soit finalement transformé en unlist
moyen de fonctionner avec des générateurs (contrairement à plusieurs des autres réponses).Production:
la source
list()
conversion en premier lieu?En voici un qui utilise la récursivité:
la source
new_data = copy.copy(data)
- cette ligne est redondante pour autant que je vois, elle n'influence rienCe one-liner vous donne toutes les combinaisons (entre les éléments
0
etn
si la liste / l'ensemble d'origine contientn
des éléments distincts) et utilise la méthode nativeitertools.combinations
:Python 2
Python 3
La sortie sera:
Essayez-le en ligne:
http://ideone.com/COghfX
la source
['b', 'a']
.TypeError: can only concatenate list (not "map") to list
Je suis d'accord avec Dan H que Ben a en effet demandé toutes les combinaisons.
itertools.combinations()
ne donne pas toutes les combinaisons.Un autre problème est que si l'entrée itérable est grande, il est peut-être préférable de renvoyer un générateur au lieu de tout dans une liste:
la source
Il s'agit d'une approche qui peut être facilement transférée à tous les langages de programmation prenant en charge la récursivité (pas d'outils itert, pas de rendement, pas de compréhension de liste) :
la source
Vous pouvez générer toutes les combinaisons d'une liste en python en utilisant ce code simple
Le résultat serait:
la source
Je pensais que j'ajouterais cette fonction pour ceux qui recherchent une réponse sans importer d'itertools ou d'autres bibliothèques supplémentaires.
Utilisation du générateur de rendement simple:
Sortie de l'exemple d'utilisation ci-dessus:
la source
Voici encore une autre solution (one-liner), impliquant l'utilisation de la
itertools.combinations
fonction, mais ici nous utilisons une compréhension à double liste (par opposition à une boucle for ou à une somme):Démo:
la source
production
la source
Vous trouverez ci-dessous une "réponse récursive standard", similaire à l'autre réponse similaire https://stackoverflow.com/a/23743696/711085 . (En réalité, nous n'avons pas à nous soucier de manquer d'espace de pile car il n'y a aucun moyen de traiter toutes les N! Permutations.)
Il visite chaque élément tour à tour et le prend ou le quitte (nous pouvons voir directement la cardinalité 2 ^ N de cet algorithme).
Démo:
la source
Utilisation de la compréhension de liste:
La sortie serait:
la source
Ce code utilise un algorithme simple avec des listes imbriquées ...
la source
""
).Je sais qu'il est beaucoup plus pratique d'utiliser itertools pour obtenir toutes les combinaisons, mais vous pouvez y parvenir en partie avec seulement une compréhension de la liste si vous le souhaitez, étant donné que vous voulez coder beaucoup
Pour les combinaisons de deux paires:
Et, pour les combinaisons de trois paires, c'est aussi simple que cela:
Le résultat est identique à l'utilisation d'itertools.combinations:
la source
Sans utiliser itertools:
la source
Voici deux implémentations de
itertools.combinations
Celui qui renvoie une liste
On retourne un générateur
Veuillez noter qu'il est conseillé de fournir une fonction d'assistance à ceux-ci car l'argument de préfixe est statique et ne change pas à chaque appel.
Ceci est un cas très superficiel mais mieux vaut prévenir que guérir
la source
Que diriez-vous de cela ... utilisé une chaîne au lieu de liste, mais la même chose .. chaîne peut être traitée comme une liste en Python:
la source
Combinaison d'itertools
Merci
la source
Sans
itertools
Python 3, vous pourriez faire quelque chose comme ceci:où au départ
carry = "".
la source
3 fonctions:
la source
Ceci est ma mise en œuvre
la source
Vous pouvez également utiliser la fonction PowerSet de l'excellent
more_itertools
package.Nous pouvons également vérifier qu'il répond aux exigences de l'OP
la source
la source
Si quelqu'un cherche une liste inversée, comme je l'étais:
la source
la source