How to detect the last element in a for loop

Eddie Corns eddie at holyrood.ed.ac.uk
Tue Aug 6 13:55:04 EDT 2002


Tom Verbeure <tom.verbeure at verizon.no.sp.am.net> writes:


>Hello All,

>I often have the case where I need to loop through a bunch of elements, but 
>do something special on for the last line of code. 

>Currently, I can solve it this way:

>    first = 1
>    for port in self.portDefsList:
>        if first == 0:
>            string += ", "
>        else:
>            first = 0
>        string += str(port)
>        pass

Here's my little contribution, though it's probably anti-pythonic.  I often
find myself writing little loops and having to know either whether I'm at a
special position or interacting with preceding/following value(s) so I created
step_thru.  In your case it would do:

  for prev,port,_ in step_thru (self.portDefsList):
      if not prev:
          string += ', '
      string += str(port)

and it looks like this:
def step_thru (seq, after=1, before=1, missing=None, apply=None):
    """
    Iterate through sequence including items before and after current.

    returns every item in sequence but also return _before_ number of items that
    precedes current and _after_ number of items that follow.
    Non-current items that don't exist are represented by _missing_.
    If apply is given it is applied to each item in the sequence (but not the
    _missing_ items).

    Example:
    for prev,curr,_ in step_thru (sys.stdin, apply=int):
      if prev: print curr - prev

    Makes no assumptions about what's in seq or whether it is bounded or not.

    In general it probably makes most sense to use the keyword argument form
    but the most common use of args will probably be to skip the afters so that
    is given first.

    If you're using pattern matching to destructure the result remember to use
    a value for _missing_ that fits. eg:
       for (prevA,prevB),(currA,currB),_ in step_thru (x,missing=(None,None))

    See also: enumerate() (PEP 279)
    for i,item in enumerate(seq):
      if i > 0: do_something (item,seq[i-1])
    would suffice for many tasks.
    """
    # when building return list we need to know how many values user wants
    w = before+after+1
    # initialise return values to have no befores
    values = [missing] * before
    # if we have to look ahead we need to keep track of how many times we need
    # to pad at the end so that main value is always returned as current
    outstanding = 0

    for i in seq:
        if apply:
            i = apply(i)
        values.append (i)
        if len(values) == w:
            yield values
            del values[0]
        else:
            outstanding += 1

    while outstanding > 0:
        values.append (missing)
        if len(values) == w:
            yield values
            del values[0]
            outstanding -= 1


------------
It has been tested a fair bit but not exhaustively.

If you don't like it - don't use it!

Eddie



More information about the Python-list mailing list