127 votes

Boucles For imbriquées sur une seule ligne

J'ai écrit cette fonction en python qui transpose une matrice :

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

Au cours de ce processus, j'ai réalisé que je ne comprenais pas entièrement comment s'exécutent les boucles for imbriquées sur une seule ligne. Veuillez m'aider à comprendre en répondant aux questions suivantes :

  1. Quel est l'ordre dans lequel cette boucle for s'exécute ?
  2. Si j'avais une triple boucle for imbriquée, dans quel ordre s'exécuterait-elle ?
  3. Qu'est-ce qui serait égal à la boucle for non imbriquée ?

Étant donné,

[ function(i,j) for i,j in object ]
  1. Quel type d'objet doit être utilisé pour utiliser cette structure de boucle ?
  2. Quel est l'ordre dans lequel i et j sont affectés aux éléments de l'objet ?
  3. Peut-on le simuler par une structure de boucle for différente ?
  4. Cette boucle for peut-elle être imbriquée avec une boucle for de structure similaire ou différente ? Et comment cela se présenterait-il ?

Les informations complémentaires sont également appréciées.

210voto

Jeff Tratner Points 4825

La meilleure source d'information est le tutoriel officiel Python sur les compréhensions de listes . Les compréhensions de liste sont presque les mêmes que les boucles for (certainement n'importe quelle compréhension de liste peut être écrite comme une boucle for) mais elles sont souvent plus rapides que l'utilisation d'une boucle for.

Regardez cette liste plus longue de compréhension du tutoriel (le if filtre la compréhension, seules les parties qui passent l'instruction if sont transmises à la partie finale de la compréhension de la liste (ici (x,y) ) :

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

C'est exactement la même chose que cette boucle for imbriquée (et, comme le dit le tutoriel, notez que l'ordre de for et if est le même).

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Les principaux différence entre une compréhension de liste et une boucle for est que la partie finale de la boucle for (où vous faites quelque chose) vient au début plutôt qu'à la fin.

J'en viens à vos questions :

Quel type d'objet doit être utilisé pour utiliser cette structure de boucle ?

Un site itérable . Tout objet qui peut générer un ensemble (fini) d'éléments. Il s'agit notamment de tout conteneur, liste, ensemble, générateur, etc.

Quel est l'ordre dans lequel i et j sont affectés aux éléments de l'objet ?

Ils sont assignés exactement dans le même ordre qu'ils sont générés à partir de chaque liste, comme s'ils étaient dans une boucle for imbriquée (pour votre première compréhension, vous obtiendriez 1 élément pour i, puis chaque valeur de j, 2e élément dans i, puis chaque valeur de j, etc.)

Peut-on le simuler par une structure de boucle for différente ?

Oui, déjà montré ci-dessus.

Cette boucle for peut-elle être imbriquée avec une boucle for de structure similaire ou différente ? Et comment cela se présenterait-il ?

Bien sûr, mais ce n'est pas une bonne idée. Ici, par exemple, on vous donne une liste de listes de personnages :

[[ch for ch in word] for word in ("apple", "banana", "pear", "the", "hello")]

42voto

nooodl Points 1302

Vous pourriez être intéressé par itertools.product qui renvoie un itérable contenant des tuples de valeurs provenant de tous les itérables que vous lui avez passés. C'est-à-dire, itertools.product(A, B) donne toutes les valeurs de la forme (a, b) où le a les valeurs proviennent de A et le b les valeurs proviennent de B . Par exemple :

import itertools

A = [50, 60, 70]
B = [0.1, 0.2, 0.3, 0.4]

print [a + b for a, b in itertools.product(A, B)]

Cette empreinte :

[50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]

Remarquez comment le dernier argument passé à itertools.product est celle qui est "intérieure". En général, itertools.product(a0, a1, ... an) est égal à [(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]

4voto

korylprince Points 1732

Tout d'abord, votre premier code n'utilise pas une boucle for à proprement parler, mais une compréhension de la liste .

  1. Serait équivalent à

    pour j dans l'intervalle(0, largeur) : pour i dans l'intervalle(0, hauteur) : m[i][j]

  2. De la même manière, elle s'imbrique généralement comme les boucles for, de droite à gauche. Mais la syntaxe de la compréhension de liste est plus complexe.

  3. Je ne suis pas sûr de ce que cette question demande.


  1. Tout objet itérable qui génère des objets itérables qui génèrent exactement deux objets (ce qui n'est pas peu dire). [(1,2),'ab'] serait valable )

  2. L'ordre dans lequel l'objet cède lors de l'itération. i va au premier rendement, j le second.

  3. Oui, mais pas aussi jolie. Je crois que c'est fonctionnellement équivalent à :

    l = list()
    for i,j in object:
        l.append(function(i,j))

    ou mieux encore, utilisez carte :

    map(function, object)

    Mais bien sûr, la fonction devrait obtenir i , j lui-même.

  4. N'est-ce pas la même question qu'au point 3 ?

2voto

Muhammad Abbas Points 125

Vous pouvez utiliser deux boucles for dans la même ligne en utilisant zip fonction

Code :

list1 = ['Abbas', 'Ali', 'Usman']
list2 = ['Kamran', 'Asgar', 'Hamza', 'Umer']
list3 = []
for i,j in zip(list1,list2):
    list3.append(i)
    list3.append(j)
print(list3)

Sortie :

['Abbas', 'Kamran', 'Ali', 'Asgar', 'Usman', 'Hamza']

Ainsi, en utilisant la fonction zip, nous pouvons utiliser deux boucles for ou nous pouvons itérer deux listes dans la même ligne.

-4voto

Code ci-dessous pour les meilleurs exemples de boucles imbriquées, tout en utilisant deux boucles for s'il vous plaît rappelez-vous la sortie de la première boucle est l'entrée pour la deuxième boucle. La terminaison de boucle est également importante lors de l'utilisation de boucles imbriquées.

for x in range(1, 10, 1):
     for y in range(1,x):
             print y,
        print
OutPut :
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X