Éviter les boucles imbriquées

J'essaie de faire des tests de paramètres sur un autre code en utilisant python. J'ai besoin de tester 6 paramètres indépendants, mais j'ai besoin de toutes les combinaisons possibles d'entre eux.

Chaque paramètre a un minimum, un maximum et une valeur de pas à lui transmettre. La première solution facile qui a surgi dans ma tête était une structure de boucle imbriquée qui avait l'air horrible, comme ceci:

for var1 in xrange(min1,max1,step1):
    for var2 in xrange(min2,max2,step2):
        ...
            ...
                ...
                    for var6 in xrange(min6,max6,step6):
                        '''
                        Do something and be icky in the process due
                        to being in the middle of six nested for loops
                        '''

J'ai décidé, non! Ce ne résistera pas. J'ai donc essayé de trouver un moyen de le faire récursivement, ou à tout le moins, Non imbriqué six fois. Je ne peux pas vraiment trouver un bon plan pour le faire. Le plus grand obstacle pour moi est que chaque variable a une valeur MIN, max et step différente.

Mes pensées jusqu'à présent ne sont pas très utiles. Je continue à essayer de faire fonctionner une fonction récursive, mais je ne peux tout simplement pas le comprendre sans imbriquer plus de boucles dans la fonction. J'ai vu beaucoup de référence à itertools.produit ici, mais je ne peux pas tout à fait comprendre comment faire ce travail soit.

Edit: ce que je fais est de créer un répertoire nommé d'après la combinaison des paramètres, d'écrire un fichier avec ces paramètres, d'exécuter un autre code avec ce fichier et d'analyser la sortie de ce code. Je ne fais rien dans littéralement l'une des boucles for sauf pour la dernière. Beaucoup de paramètres ont 2 valeurs, certains ont 10, d'autres ont 3... c'est en quelque sorte varie.

23
demandé sur Benjamin 2012-06-24 07:30:11

2 réponses

Voici comment utiliser product:

x1 = xrange(min1,max1,step1)
x2 = xrange(min2,max2,step2)
x3 = xrange(min3,max3,step3)
...

for v1, v2, v3, v4, v5, v6 in itertools.product(x1, x2, x3, x4, x5, x6):
    icky_thing(....)

, Ou un peu plus compacte:

ranges = [
    xrange(min1,max1,step1),
    xrange(min2,max2,step2),
    xrange(min3,max3,step3),
    ...
]

for v1, v2, v3, v4, v5, v6 in itertools.product(*ranges):
    icky_thing(....)
39
répondu Ned Batchelder 2012-06-24 03:33:19

Vous pouvez probablement utiliser itertools.product: http://docs.python.org/library/itertools.html#itertools.product .

Quelque Chose comme

for var1, var2 in itertools.product(xrange(min1, max1, step1), xrange(min2, max2, step2)):
    # stuff

. . . seulement avec les six vars là-dedans.

14
répondu BrenBarn 2012-06-24 03:31:51