9
votes

Python iTerTools.Produits Réorganiser la génération

J'ai ceci: xxx

jusqu'à présent, si bon, iteroTools.Production avance l'élément le plus à droite sur chaque itération. Mais maintenant, je veux être capable de spécifier l'ordre d'itération selon les éléments suivants: xxx

si formes avait trois dimensions, axes < / Code> aurait pu être par exemple (0, 1, 2) ou (2, 0, 1) etc., il ne s'agit pas de simplement utiliser inversé () . Donc, j'ai écrit du code qui le fait, mais semble très inefficace: xxx

aucune idée sur la manière de le faire correctement?


7 commentaires

Pour vos exemples TPaxes est [1, 0] et axes est (1, 0) . Vous voudrez peut-être changer vos données d'exemple pour plus de clarté afin qu'ils soient différents :)


True, Axes = TPaxes parce que c'est le seul moyen possible de réorganiser les axes d'une matrice 2D. Pour une matrice 3D, ce n'est pas le cas. Si les axes étaient (2, 0, 1) , les TPaxes seront (1, 2, 0) par exemple.


Je sais - je voulais juste souligner qu'un exemple plus compliqué serait mieux dans ce cas; Aucune infraction.


La seule façon de le faire sans une étape supplémentaire consiste à écrire votre propre implémentation de produit . Je lie à un couple que vous pourriez commencer par Cet article sur iTerTools.Production de l'autre jour. Ma question est pourquoi . Si vous aviez vraiment besoin de le faire dans une situation spécifique, vous venez de réorganiser les arguments que vous avez nourris au produit dans le bon ordre de commencer, et vous n'avez pas besoin de changer l'ordre de la génération.


Vous ne pouvez pas simplement trier la sortie du produit après le fait?


Désolé si je ne suis pas complètement à la suite de votre logique, mais pourquoi ne pas réorganiser la première fois les gammes que vous passez à produit ? Voulez-vous modifier l'ordre des axes (comme dans l'exemple) ou plutôt l'ordre d'itération (alors la 2e sortie serait (0, 0), (1, 0), (0, 1), ( 1, 1), (0, 2), (1, 2), (0, 3), (1, 3) )


Ah, maintenant je vois, vous voulez changer, commandes et commande d'itération ...


6 Réponses :


0
votes
for i in itertools.product(*(range(x) for x in reversed(shape))):
    print tuple(reversed(i))

2 commentaires

Cela fonctionne dans le cas 2D, mais j'aimerais pouvoir spécifier la manière dont les axes sont inversés. J'ai mis à jour la question pour refléter cela plus clairement.


@Giovannifunchunchor alors je pense que votre approche est bien: tuple (i [y] pour y dans tpaxes)



1
votes

Je ne sais pas à quel point cela est efficace, mais vous devriez être capable de faire quelque chose comme ça ...

shape = (2, 4, 3)
axes = (2, 0, 1)

# Needed to get the original ordering back
axes_undo = tuple(reversed(axes))

# Reorder the shape in a configuration so that .product will give you
# the order you want.
reordered = tuple(reversed(map(lambda x: shape[x], list(axes))))

# When printing out the results from .product, put the results back
# into the original order.
for i in itertools.product(*(range(x) for x in reordered)):
    print(tuple(map(lambda x: i[x], list(axes_undo))))


0 commentaires

1
votes

Avez-vous essayé de chronométrer pour voir combien de temps il faut? Ce que vous n'avez pas ne devrait pas être beaucoup plus lent que sans réorganisation.

Vous pouvez essayer de modifier ce que vous devez utiliser une affectation d'épissure de place. P>

tpaxes = tuple(tpaxes)
for i in itertools.product(*(range(x) for x in shape)):
    # reorder the output of itertools.product
    i[:] = (i[y] for y in tpaxes)
    print(tuple(x))


0 commentaires

7
votes

Eh bien, c'est en fait un manuel spécialisé produit . Il devrait être plus rapide car les axes sont réorganisés une seule fois: xxx


0 commentaires

5
votes

Si vous pouvez vous le permettre Memory-Wise: Laissez itheroTools.Product code> Faites le travail acharné et utilisez zip code> pour commuter les axes autour.

>>> print(*product((2, 2, 4), (1, 2, 0)))
(0, 0, 0) (1, 0, 0) (2, 0, 0) (3, 0, 0) (0, 0, 1) (1, 0, 1) (2, 0, 1) (3, 0, 1) (0, 1, 0) (1, 1, 0) (2, 1, 0) (3, 1, 0) (0, 1, 1) (1, 1, 1) (2, 1, 1) (3, 1, 1)


7 commentaires

+1, j'aime particulièrement la solution eval . C'est un morceau de codage créatif que l'on ne voit pas tous les jours! Cela pourrait être moche, mais c'est plutôt clair ce que cela fait et si la performance est vraiment critique, je pense que c'est le seul moyen :)


HM, où est (0, 0, 3) provenant de, le dernier axe devrait être déplacé au milieu, ne devrait-il pas?


@berer: les valeurs d'axe 1 sont d'abord augmentées, puis d'axe 2, puis d'axe 0. Quelles valeurs apparaissent sur lesquelles l'axe n'est pas affecté par le paramètre (code>; Il ne détermine que l'ordre dans lequel les valeurs sont augmentées.


@Wolframh dans l'exemple de OP avec des paires, l'ordre des axes est modifié.


Pour autant que je sache, les 4 axes (le dernier, ayant indice 2) doivent être déplacés vers le milieu dans le résultat, car (1, 2, 0) place là-bas. Donc, il devrait y avoir (0, 3, 0) , pas (3, 0, 0) .


@beraler: J'ai vérifié ma sortie contre le code de l'OP et c'était OK. Obtenez-vous (0,3,0) ou (3,0,0) lors de l'exécution du code de l'OP?


@Wolframh, ah enfin, je reçois la logique de l'Op. 0 Dans la dernière position, cela devrait signifier que le dernier axe va au premier. OK merci.



0
votes
(0, 0) (0, 0)
(0, 1) (1, 0)
(0, 2) (2, 0)
(0, 3) (3, 0)
(1, 0) (0, 1)
(1, 1) (1, 1)
(1, 2) (2, 1)
(1, 3) (3, 1)

0 commentaires