views:

260

answers:

3

Let's say I have 2 lists in Python and I want to loop through each one in parallel - e.g. do something with element 1 for both lists, do something with element 2 for both lists... I know that I can do this by using an index:

for listIndex in range(len(list1)):
   doSomething(list1[listIndex])
   doSomething(list2[listIndex])

But is there a way to do this more intuitively, with a foreach loop? Something like for list1Value in list1, list2Value in list2...?

I've currently run into this situation in Python, but this is a longstanding question and I'd be interested to know if you can do this in any language. (I just assumed that Python is the most likely to have a method of dealing with this.)

+11  A: 

Something like this?

for (a,b) in zip(list1, list2):
  doSomething(a)
  doSomething(b)

Though if doSomething() isn't doing I/O or updating global state, and it just works on one of the elements at a time, the order doesn't matter so you could just use chain() (from itertools):

for x in chain(list1, list2):
  doSomething(x)

Apropos, from itertools import * is something I do very often. Consider izip() instead of using the zip() I gave above. Also look into izip_longest(), izip(count(), lst), etc. Welcome to functional programming. :-)

Oh, and zipping also works with more "columns":

for idx, a, b, c in izip(count(), A, B, C):
  ...
integer
+1 for `itertool.chain()`!
EOL
one example of no globality and no applicability of chain: `for item1, item2 in zip(iter1, iter2): fileobj.write("%s %s\n" % (item1, item2))`
ΤΖΩΤΖΙΟΥ
thanks this is great! just a quick question... does this method require the lists to be of the same length? what happens if they're not?
froadie
It stops as soon as the shorter list is exhausted.
Tim Pietzcker
@froadie, you can use izip_longest() to make it 'pad' the shortest lists with fill values (defaults to None).Also, updated answer somewhat.
integer
Second example, shouldn't it be `doSomething(x)`?
Javier Badia
@Javier, oops. :-)
integer
+4  A: 

That will depend on the language. Python actually has a rather simple method for that:

a = (0,1,2,3,4,5,6,7,8,9)
b = "ABCDEFGHIJ"
for pair in zip(a,b):
  print("%d => %s" % pair)
Korbinian
+4  A: 

Use zip or itertools.izip for this:

for item1, item2 in zip(iterable1, iterable2):
    # process the items in parallel

itertools.izip in Python < 3 and zip in Python ≥ 3 return iterators; i.e. they provide tuples of pairs (or triplets, quartets etc) on request. Python < 3 zip creates a list of tuples, so the memory requirements could be large if the smallest of the sequences is quite long.

ΤΖΩΤΖΙΟΥ
zip seems to work in python 2.6 as well
froadie
@froadie: I never said it doesn't work.
ΤΖΩΤΖΙΟΥ