156 votes

"for loop" avec deux variables ?

Comment puis-je inclure deux variables dans le même for boucle ?

t1 = [a list of integers, strings and lists]
t2 = [another list of integers, strings and lists]

def f(t):  #a function that will read lists "t1" and "t2" and return all elements that are identical
    for i in range(len(t1)) and for j in range(len(t2)):
        ...

242voto

SethMMorton Points 4704

Si vous voulez l'effet d'une boucle for imbriquée, utilisez :

import itertools
for i, j in itertools.product(range(x), range(y)):
    # Stuff...

Si vous voulez juste boucler simultanément, utilisez :

for i, j in zip(range(x), range(y)):
    # Stuff...

Notez que si x y y ne sont pas de la même longueur, zip tronquera la liste la plus courte. Comme @abarnert l'a souligné, si vous ne voulez pas tronquer à la liste la plus courte, vous pouvez utiliser itertools.zip_longest .

UPDATE

Sur la base de la demande d'une "fonction qui lira les listes "t1" et "t2" et retournera tous les éléments qui sont identiques", je ne pense pas que le PO veut zip ou product . Je pense qu'ils veulent un set :

def equal_elements(t1, t2):
    return list(set(t1).intersection(set(t2)))
    # You could also do
    # return list(set(t1) & set(t2))

Le site intersection méthode d'un set retournera tous les éléments communs à celui-ci et à un autre ensemble (Notez que si vos listes contiennent d'autres list vous voudrez peut-être convertir l'élément interne list s à tuples d'abord pour qu'ils soient hachables ; sinon, l'appel à set échouera). Le site list transforme ensuite l'ensemble en une liste.

MISE À JOUR 2

OU, le PO peut vouloir des éléments qui sont identiques dans les domaines suivants la même position dans les listes . Dans ce cas, zip serait le plus approprié, et le fait qu'il tronque à la liste la plus courte est ce que vous voudriez (puisqu'il est impossible qu'il y ait le même élément à l'indice 9 quand l'une des listes n'a que 5 éléments). Si c'est ce que vous voulez, optez pour cette solution :

def equal_elements(t1, t2):
    return [x for x, y in zip(t1, t2) if x == y]

Cela renverra une liste contenant uniquement les éléments qui sont identiques et à la même position dans les listes.

93voto

Morgan Harris Points 2359

Il y a deux questions possibles ici : comment pouvez-vous itérer sur ces variables ? simultanément ou comment faire une boucle sur leur combinaison .

Heureusement, il existe des réponses simples à ces deux questions. Dans le premier cas, vous voulez utiliser zip .

x = [1, 2, 3]
y = [4, 5, 6]

for i, j in zip(x, y):
   print(str(i) + " / " + str(j))

produira

1 / 4
2 / 5
3 / 6

N'oubliez pas que vous pouvez mettre tout itérable en zip donc vous pourriez tout aussi bien écrire votre exemple comme ça :

for i, j in zip(range(x), range(y)):
    # do work here.

En fait, je viens de réaliser que ça ne marchera pas. Il ne ferait qu'itérer jusqu'à ce que la plus petite plage soit épuisée. Dans ce cas, il semble que vous vouliez itérer sur la combinaison de boucles.

Dans l'autre cas, vous voulez simplement une boucle imbriquée.

for i in x:
    for j in y:
        print(str(i) + " / " + str(j))

vous donne

1 / 4
1 / 5
1 / 6
2 / 4
2 / 5
...

Vous pouvez également le faire sous forme de compréhension de liste.

[str(i) + " / " + str(j) for i in range(x) for j in range(y)]

J'espère que cela vous aidera.

21voto

Jags Points 718

Y a-t-il une raison pour laquelle vous ne pouvez pas utiliser une boucle for imbriquée ?

for i in range(x):
   for j in range(y):
       #code that uses i and j

17voto

qaphla Points 3289
for (i,j) in [(i,j) for i in range(x) for j in range(y)]

devrait le faire.

9voto

kojiro Points 24374

Si vous n'avez besoin que d'une itération pas à pas sur une plage, vous pouvez le faire de plusieurs façons :

for i in range(x):
  j = i
  …
# or
for i, j in enumerate(range(x)):
  …
# or
for i, j in ((i,i) for i in range(x)):
  …

Tout ce qui précède est équivalent à for i, j in zip(range(x), range(y)) si x <= y .

Si vous voulez une boucle imbriquée et que vous n'avez que deux itérables, utilisez simplement une boucle imbriquée :

for i in range(x):
  for i in range(y):
    …

Si vous avez plus de deux itérables, utilisez itertools.product .

Enfin, si vous voulez une itération pas à pas jusqu'à x et ensuite de continuer à y vous devez décider ce que le reste de l'histoire x les valeurs devraient être.

for i, j in itertools.zip_longest(range(x), range(y), fillvalue=float('nan')):
  …
# or
for i in range(min(x,y)):
  j = i
  …
for i in range(min(x,y), max(x,y)):
  j = float('nan')
  …

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