Comment puis-je inclure deux variables dans la même boucle for
?
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)):
...
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 faire une boucle simultanément, utilisez:
for i, j in Zip(range(x), range(y)):
# Stuff...
Notez que si x
et y
ne sont pas de même longueur, Zip
sera tronqué à la liste la plus courte. Comme @abarnert l'a fait remarquer, si vous ne voulez pas être tronqué à la liste la plus courte, vous pouvez utiliser itertools.Zip_longest
.
UPDATE
Sur la base de la demande "d'une fonction qui lit les listes" t1 "et" t2 "et renvoie tous les éléments identiques", je ne pense pas que l'OP souhaite 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))
La méthode intersection
d'un set
renverra tous les éléments qui lui sont communs et un autre ensemble (notez que si vos listes contiennent d'autres list
s, vous voudrez peut-être convertir les list
s internes en tuples
de façon à ce qu'ils soient exécutables; sinon, l'appel à set
échouer.). La fonction list
transforme ensuite le poste en liste.
PDATE 2
OU, le PO peut vouloir des éléments identiques dans à la même position dans les listes . Dans ce cas, Zip
serait le plus approprié, et le fait qu'il soit tronqué sur la liste la plus courte est ce que vous souhaiteriez (puisqu'il est impossible qu'il y ait le même élément à l'index 9 lorsque l'une des listes ne contient que 5 éléments ) Si c'est ce que vous voulez, allez avec ceci:
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 identiques et placés à la même position dans les listes.
Il y a deux questions possibles ici: comment itérer sur ces variables simultanément , ou comment passer en boucle sur leur combinaison .
Heureusement, il existe des réponses simples aux deux. 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))
va sortir
1 / 4
2 / 5
3 / 6
Rappelez-vous que vous pouvez mettre tout type itérable dans Zip
, de sorte que vous puissiez tout aussi bien écrire votre exemple comme ceci:
for i, j in Zip(range(x), range(y)):
# do work here.
En fait, je viens de me rendre compte que cela ne marchera pas. Cela ne ferait que répéter jusqu'à épuisement de la plage. Dans ce cas, il semblerait que vous souhaitiez parcourir la combinaison de boucles.
Dans l'autre cas, vous voulez juste 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 en tant que compréhension de liste.
[str(i) + " / " + str(j) for i in range(x) for j in range(y)]
J'espère que ça t'as aidé.
Vous ne pouvez pas utiliser une boucle imbriquée?
for i in range(x):
for j in range(y):
#code that uses i and j
for (i,j) in [(i,j) for i in range(x) for j in range(y)]
devrait le faire.
Si vous avez vraiment juste une itération de verrouillage sur une plage, vous pouvez le faire de plusieurs manières:
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)):
…
Toutes ces réponses sont équivalentes à for i, j in Zip(range(x), range(y))
si x <= y
.
Si vous voulez une boucle imbriquée et que vous ne disposez que de 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
, puis que vous continuiez à y
, vous devez décider de ce que devrait être le reste des valeurs x
.
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')
…
"Python 3."
Ajoutez 2 vars avec une boucle for en utilisant Zip et range; Renvoyer une liste.
Remarque: ne fonctionnera que jusqu’à la fin de la plus petite plage.
>>>a=[g+h for g,h in Zip(range(10), range(10))]
>>>a
>>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Je pense que vous recherchez des boucles imbriquées.
Exemple (basé sur votre modification):
t1=[1,2,'Hello',(1,2),999,1.23]
t2=[1,'Hello',(1,2),999]
t3=[]
for it1, e1 in enumerate(t1):
for it2, e2 in enumerate(t2):
if e1==e2:
t3.append((it1,it2,e1))
# t3=[(0, 0, 1), (2, 1, 'Hello'), (3, 2, (1, 2)), (4, 3, 999)]
Ce qui peut être réduit à une seule compréhension:
[(it1,it2,e1) for it1, e1 in enumerate(t1) for it2, e2 in enumerate(t2) if e1==e2]
Mais pour trouver les éléments communs, vous pouvez simplement faire:
print set(t1) & set(t2)
# set([(1, 2), 1, 'Hello', 999])
Si votre liste contient des objets non-hashable (comme d'autres listes, dict), utilisez un ensemble figé:
from collections import Iterable
s1=set(frozenset(e1) if isinstance(e1,Iterable) else e1 for e1 in t1)
s2=set(frozenset(e2) if isinstance(e2,Iterable) else e2 for e2 in t2)
print s1 & s2
Pour votre cas d'utilisation, il peut être plus facile d'utiliser une boucle while
.
t1 = [137, 42]
t2 = ["Hello", "world"]
i = 0
j = 0
while i < len(t1) and j < len(t2):
print t1[i], t2[j]
i += 1
j += 1
# 137 Hello
# 42 world
En guise de mise en garde, cette approche sera tronquée à la longueur de votre liste la plus courte.