2
votes

Fonction de générateur Python et permutations

Saisie du problème: deux listes [1,2,3] et [4,5,6]

Sortie: listes commençant par une permutation de [1,2,3] suivie d'une permutation de [4,5,6]

Les exemples de sorties sont [1,2,3,4,5,6] , [3,2,1,4,5,6] , [3,2,1,6,5,4] etc. Je veux faire une boucle à travers eux en utilisant un générateur.

J'ai essayé avec le script suivant (Python3):

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 6, 5]
[1, 2, 3, 5, 4, 6]
[1, 2, 3, 5, 6, 4]
[1, 2, 3, 6, 4, 5]
[1, 2, 3, 6, 5, 4]

Comme sorties je reçois

from itertools import permutations

def foo():
    perm_1 = permutations([1,2,3])
    perm_2 = permutations([4,5,6])

    for p1 in perm_1:
        for p2 in perm_2: 
            yield list(p1) + list(p2)

f = foo()

for ls in f:
    print(ls)

Comme vous pouvez le voir, les permutations de la première liste ne sont jamais utilisées et par exemple, la sortie [3,2,1,4,5,6] n'est jamais produite.


0 commentaires

3 Réponses :


2
votes

Le problème ici est que, une fois itéré, perm2 sera vide.

Ainsi, lors de la première itération de la boucle for externe, tout va bien. Sur les itérations suivantes, cependant, perm2 sera juste vide.

Voir un exemple plus simple ici:

>>> from itertools import permutations
>>> a = permutations([1,2,3])
>>> list(a)
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
>>> list(a)
[]

Pour le résoudre, remplacez perm_2 par des permutations([4,5,6])

(Une autre solution pourrait être de convertir perm_2 en list lors du stockage mais je pense que tout garder avec des générateurs est plus idiomatique)


1 commentaires

Je savais que c'était quelque chose de simple embarrassant!



1
votes

Le problème est ici:

perm_1 = list(permutations([1,2,3])) 
perm_2 = list(permutations([4,5,6])) 

Une fois que vous chargez les permutations cela ne vous reviendra plus jamais pour la boucle.

essayez plutôt ceci et obtenez chacun d'eux sous forme de liste:

perm_1 = permutations([1,2,3])
perm_2 = permutations([4,5,6])


0 commentaires

1
votes

Je pense que cela se produit parce que la méthode de permutation d'itertool est implémentée comme une fonction de générateur sous le capot. Puisque vous utilisez une boucle for imbriquée, avec p1 = (1, 2, 3) , perm_2 génère toutes les permutations possibles des nombres de la liste [4, 5, 6] et s'épuise. Il n'est pas possible d'itérer plus d'une fois sur les fonctions / expressions du générateur, c'est pourquoi la boucle se termine simplement par un ordre possible à partir de perm_1 .


0 commentaires