web-dev-qa-db-ja.com

2つの変数を持つ "forループ"?

同じforループに2つの変数を含めるにはどうすればいいですか?

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)):
        ...
90
Quester

ネストされたforループの効果が必要な場合は、次を使用します。

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

同時にループするだけの場合は、次を使用します。

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

xyの長さが同じでない場合、Zipは最も短いリストに切り捨てられることに注意してください。 @abarnertが指摘したように、最短のリストに切り捨てたくない場合は、itertools.Zip_longestを使用できます。

UPDATE

「リスト「t1」と「t2」を読み取り、同一のすべての要素を返す関数」の要求に基づいて、OPはZiporproduct。私は彼らがsetを望んでいると思う:

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

intersectionsetメソッドは、それに共通するすべての要素と別のセットを返します(リストに他のlistsが含まれている場合は、最初に内部のlistsをtuplesに変換してハッシュ可能にするか、そうでない場合はsetを呼び出します失敗します。)。 list関数は、セットをリストに戻します。

更新2

または、OPはリスト内の同じ位置で同一の要素を必要とする場合があります。この場合、Zipが最も適切であり、最短のリストに切り捨てられるという事実が必要です(リストの1つが5要素のみの場合、インデックス9に同じ要素が存在することは不可能であるため) )。それがあなたが望むものであるならば、これで行ってください:

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

これにより、リスト内の同じ位置にある同じ要素のみを含むリストが返されます。

169
SethMMorton

ここで考えられる質問が2つあります。それらの変数をどのように反復することができますか同時に、またはどのようにそれらの変数をループ処理することができます組み合わせ

幸い、両方に簡単な答えがあります。最初のケースでは、あなたはZipを使いたいのです。

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

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

出力します

1 / 4
2 / 5
3 / 6

Zipany iterableを入れることができることを忘れないでください。そのため、以下のように簡単に例を書くことができます。

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

実際には、うまくいかないことに気づいただけです。小さい範囲がなくなるまで繰り返します。その場合は、ループの組み合わせを反復処理したいようです。

それ以外の場合は、ネストループが必要です。

for i in x:
    for j in y:
        print i + " / " + j

あなたにあげる

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

リスト内包としてこれを行うこともできます。

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

それが役立つことを願っています。

27
Morgan Harris

入れ子になったforループを使えない理由は何ですか?

for i in range(x):
   for j in range(y):
       #code that uses i and j
19
Jags
for (i,j) in [(i,j) for i in range(x) for j in range(y)]

それをするべきです。

11
qaphla

ある範囲で本当にロックステップの反復があるだけなら、いくつかの方法のうちの1つを実行できます。

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)):
  …

x <= yの場合、上記のすべてはfor i, j in Zip(range(x), range(y))と同等です。

ネストループが必要で、2つのイテラブルしかない場合は、ネストループを使用してください。

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

3つ以上のイテラブルがある場合はitertools.productを使用してください。

最後に、ロックステップの反復をxまで続けてからyまで続けたい場合は、残りの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')
  …
8
kojiro

「Python 3」

Zipとrangeを使用してforループを2つ追加します。リストを返す.

注:最小範囲の終わりまでしか実行されません。

>>>a=[g+h for g,h in Zip(range(10), range(10))]
>>>a
>>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
5
Open-Business

入れ子になったループを探していると思います。

例(あなたの編集に基づく):

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)]

これは単一の内包表記に還元することができます。

[(it1,it2,e1) for it1, e1 in enumerate(t1) for it2, e2 in enumerate(t2) if e1==e2] 

しかし、共通の要素を見つけるために、あなたはただすることができます:

print set(t1) & set(t2)
# set([(1, 2), 1, 'Hello', 999])

リストにハッシュ不可能なオブジェクトが含まれている場合(他のリストや辞書など)、固定セットを使用してください。

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
3
dawg

あなたのユースケースでは、 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

注意点として、このアプローチはあなたの最短リストの長さに切り捨てられます。

2
Daniel