Comment obtenir toutes les combinaisons possibles d'une liste d'éléments?
J'ai une liste de 15 numéros, et j'ai besoin d'écrire du code qui produit tous les 32,768 combinaisons de ces nombres.
J'ai trouvé un peu de code (par Googler) qui, apparemment, fait ce que je cherche, mais j'ai trouvé le code assez opaque et me méfie de l'utiliser. En Plus j'ai le sentiment il doit y avoir une solution plus élégante.
La seule chose qui me vient à l'esprit serait de simplement faire une boucle par la décimale des entiers 1-32768 et la convertir en binaire, et l'utilisation de la représentation binaire comme un filtre pour sélectionner les numéros appropriés.
Personne ne sait d'une meilleure façon? À l'aide de map()
, peut-être?
- Les lecteurs sont priés de noter que si les éléments de la liste sont unique est un élément extrêmement important de la considération, de nombreux algorithmes sera alors une surestimation de certains sous-ensemble (par exemple 'abccc' -> [", 'a', 'b', 'c', 'c', 'c', 'ca', 'ca', 'ac', ...]. Une simple solution de contournement est de pousser tous les éléments dans un ensemble avant d'obtenir leurs permutations.
Vous devez vous connecter pour publier un commentaire.
Ont un coup d'oeil à itertools.combinaisons:
Depuis la 2.6, les piles sont inclus!
list(itertools.combinations(iterable, r))
Cette réponse manqué un seul aspect: l'OP a demandé pour TOUTES les combinaisons... et pas seulement des combinaisons de longueur "r".
Donc, si vous voulez, soit disposer d'une boucle sur toutes les longueurs "L":
Ou, si vous voulez obtenir snazzy (ou de plier le cerveau de celui qui lit votre code après vous) -- vous pouvez générer la chaîne de "combinaisons()" générateurs, et itérer que:
powerset()
générateur de fonction dans les recettes de la section de laitertools
de documentation de plus simple, potentiellement utilise moins de mémoire, et est probablement plus rapide que la mise en œuvre montré ici.itertools.combinations
préserve l'ordre dans les listes de ce qu'elle cède. Ainsi, si l'entrée est lexicalement triés, puis chacune des sorties sera ainsi.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 le vocabulaire autant que je le comprends: powerset([1,2]) --> [(), (1,), (2,), (1, 2)]. Ne devrait-elle pas être : [(), (1,), (1, 2), (2,)] ?Voici un paresseux one-liner, également à l'aide de itertools:
Idée principale derrière cette réponse: il y a 2^N combinaisons -- même que le 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 objet iterable comme un générateur, la transformer en une liste d'abord avecitems=list(_itemsArg)
)items
n'est pas aléatoire (solution: ne pas être aliéné){2,2,1}
et{2,1,1}
permettra à la fois de l'effondrement du{2,1}
(solution de contournement: utilisezcollections.Counter
que d'une baisse-dans le remplacement pourset
; c'est essentiellement un multiset... mais vous devrez peut-être utiliser plus tardtuple(sorted(Counter(...).elements()))
si vous en avez besoin pour être hashable)Démo
Dans les commentaires sous le très upvoted réponse par @Dan H, mention est faite de la
powerset()
recette dans leitertools
de la documentation—y compris par Dan lui-même. Cependant, jusqu'à présent personne n'a posté une réponse. Puisque c'est probablement l'un des meilleurs si ce n'est la meilleure approche du problème et donné un peu d'encouragement à partir d'un autre intervenant, il est montré ci-dessous. La fonction produit tous combinaisons uniques de la liste des éléments de chaque longueur possible (y compris ceux contenant du zéro et de tous les éléments).Note: Si l', subtilement différentes, l'objectif est d'obtenir uniquement des combinaisons d'éléments uniques, modifiez la ligne
s = list(iterable)
às = list(set(iterable))
à éliminer tous les éléments en double. Peu importe, le fait que leiterable
est finalement transformé en unlist
signifie qu'il fonctionnera avec des générateurs (contrairement à plusieurs autres réponses).De sortie:
Ici est en utilisant la récursivité:
new_data = copy.copy(data)
- cette ligne est redondant autant que je le vois, il n'a pas d'influence sur quoi que ce soitCe one-liner vous donne toutes les combinaisons (entre
0
etn
éléments si la liste d'origine/set contientn
éléments distincts) et utilise la méthode nativeitertools.combinaisons
:Python 2
Python 3
La sortie sera:
Essayer en ligne:
http://ideone.com/COghfX
['b', 'a']
.TypeError: can only concatenate list (not "map") to list
Je suis d'accord avec Dan H Ben en effet demandé pour tous combinaisons.
itertools.combinations()
ne donne pas toutes les combinaisons.Une autre question est, si l'entrée itérable est grand, il est peut-être mieux de retourner un générateur au lieu de tout dans une liste:
Vous pouvez générer toutes les combinaisons d'une liste en python à l'aide de ce simple code
Résultat serait :
J'ai pensé que je voudrais ajouter cette fonction pour ceux qui cherchent une réponse sans import itertools ou toutes les autres bibliothèques supplémentaires.
De Rendement Simple Utilisation D'Un Générateur:
Sortie à partir de l'Utilisation de l'exemple ci-dessus:
Voici encore une autre solution (one-liner), impliquant l'aide de la
itertools.combinations
fonction, mais ici, nous utilisons une double compréhension de liste (par opposition à une boucle for ou somme):Démo:
Il pourrait être fait à l'aide de itertools
Pour les permutations
Cette méthode prend une liste en entrée et retourne un objet de la liste de tuples contenant permutation de longueur L dans un formulaire de liste.
Pour La Combinaison
Cette méthode prend une liste et une entrée r en entrée et renvoie un objet de la liste de tuples qui contiennent toutes les combinaisons possibles de longueur r dans une forme de liste.
voir cette
C'est une approche qui peut être facilement transféré à tous les langages de programmation soutenir la récursivité (pas de itertools, pas de rendement, pas de compréhension de liste):
Ci-dessous est un "standard récursive réponse", à l'instar des autres semblables réponse https://stackoverflow.com/a/23743696/711085 . (Nous n'avons pas réellement avoir à vous soucier de manquer d'espace de pile car il n'y a aucun moyen que nous pourrions traiter tous les N! permutations.)
Il visite chaque élément à son tour, et, soit qu'il le prend ou laisse (on peut voir directement la 2^N la cardinalité de cet algorithme).
Démo:
Ce code utilise un algorithme simple avec des listes imbriquées...
""
).Je sais que c'est beaucoup plus pratique à utiliser itertools pour obtenir le tous les combinaisons, mais vous peut résultats s'expliquent en partie avec seulement la compréhension de liste si vous arriver à souhait, certes vous souhaitez code beaucoup
Pour les combinaisons de deux paires:
Et, pour des combinaisons de trois paires, c'est aussi simple que cela:
Le résultat est identique à l'aide de itertools.combinaisons:
Sans l'aide de itertools:
Voici deux implémentations de
itertools.combinations
Celui qui renvoie une liste
On renvoie un générateur
Veuillez noter que le fait de fournir une fonction d'assistance à personnes est conseillé parce que le préfixe argument est statique et n'est pas en train de changer avec chaque appel
C'est très superficiel cas, mais mieux vaut prévenir que guérir
Comment à ce sujet.. utilisé une chaîne de caractères au lieu de la liste, mais la même chose.. chaîne peut être traitée comme une liste en Python:
Combinaison de itertools
Grâce
Sans
itertools
en Python 3, vous pourriez faire quelque chose comme ceci:où initialement
carry = "".
L'aide de la liste de compréhension:
Sortie:
C'est ma mise en œuvre
Si quelqu'un est à la recherche d'une inversion de la liste, comme je l'ai été: