Syntax for simultaneous "for" loops?

Markus Schaber use-net at schabi.de
Tue Feb 18 16:53:20 EST 2003


Hi,

On Mon, 17 Feb 2003 12:32:31 +0100
Alex Martelli <aleaxit at yahoo.com> wrote:

> John Ladasky wrote:   
>    ...
> > A few days ago I came across a web page which described a "for"
> > syntax, which allowed two variables to be stepped at the same time,
> > through two independent lists.  I said to myself, "that's cool, I
> > wonder when I might need that?"  Well, I need it now.  But I
> > bookmarked the relevant web page at work, and we're snowed in here!
> > 
> > Would some kind soul please point me to the relevant information?
> 
> 
> for onevar, another in zip(onelist, otherlist):
>     print onevar, another
> 
> may be what you want -- the two lists are iterated "in parallel".

This does work well for short, in-memory lists. If you have two
iterators and do not want both to be precalculated when zip() is called,
you could use something like the following Generator (needs Python 2.2
with"from __future__ import generators" statement or Python 2.3):

def seqjoin(a,b):
  aa = iter(a)
  bb = iter(b)
  while 1:
    yield aa.next(),bb.next()

This generates the new sequence "on the fly" and element for element,
thus you can safely use it with xranges, large files, stdin.xreadlines()
and other sequences that you don't want to be precalculated, or if you
expect the for iteration to be aborted by some other condition far
before reaching the end of the lists.

You use it like:

for onevar, another in seqjoin(onelist, otherlist):
  print onevar, another

If you want to pad the shorter sequence with None, you can use the
following wrapper:

def padder(a):
  for i in a:
    yield a
  while 1:
    yield None

You use it like in

for i in seqjoin(longlist, padder(shortlist)):
  print i

But be careful not to pad both sequences, as you will get an endless
loop working on (None,None) :-)

seqjoin could even be expanded to work with any number of sequences, it
even get shorter one line:

def seqjoin(*objects):
  iters = map(iter, objects)
  while 1:
    yield map(lambda a: a.next(), iters)

But note that this returns lists instead of tuples, this might make a
difference sometimes, but 

for i,j,k in seqjoin(onelist, otherlist, thirdlist): 
  print i,j,k

works nevertheless.

HTH,
Markus
-- 
Schabi's Flohmarkt: http://www.uni-ulm.de/~s_mschab/flohmarkt/

Der Dienstweg ist die Verbindung der Sackgasse mit dem Holzweg!
[DoLi in unibwm.studium]




More information about the Python-list mailing list