I see that there is a thread of a similar topic that was posted recently ( 
enumerate with a start index  ) but thought I would start a new thread since 
what I am suggesting is a little different.

Whenever I use enumerate, I am doing so because I will use the index to access 
some other element in the list (the previous or next, usually) while also 
looking at the element that is returned from enumerate.  Several times, 
however, in the development phase of the work, I end up sending a subset of the 
list at hand and then get bitten by the fact that the indices returned by 
enumerate are not the indices of the original list, they are the indices of the 
slice that I sent. e.g. in the following, "0" is the first index but I wanted 
it to be 3

###
>>> start=3
>>> count=5
>>> for i, x in enumerate(range(10)[start:start+count]):
...  print i, x
...  
0 3
1 4
2 5
3 6
4 7
>>> 
###

What I would propose is an optional slice argument to the enumerate routine 
that would allow enumerate to return elements that are synchronized with the 
original list list/iterable elements. e.g.

def enum(l, slc=None):
    if slc==None:
        for i, dat in enumerate(l):
            yield i, dat
    else:
        if type(slc)<>slice:
            raise TypeError, "slc must be a valid slice"
        start, step = slc.start, slc.step
        # we need actual values for start and step, so check for None
        # and supply defaults
        if step==None:step=1
        if start==None:
            if step>0:
                start=0
            else:
                start=-1
        for i, dat in enumerate(l[slc]):
            j = i*step+start
            if j<0: j+=len(l)
            yield j, dat
###
>>> for i, x in enum(range(10), slice(start, start+count)):
...  print i, x
...  
3 3
4 4
5 5
6 6
7 7
>>> for i, j in enum(range(10), slice(None,None,-3)):
...  print i,j
...  
9 9
6 6
3 3
0 0
>>> 
###

An advantage to processing the iteratable with a slice argument is that then 
the slice information is given only once and it can do 2 things: slice the 
original iterable and provide the synchronized indices.

NOTE: the same thing that I am proposing could also be done with count and izip 
if count had a step argument, but it's more ackward and you have to supply the 
same information in two places:

>>> def count(start, step=1):
...  for i in itertools.count(start):
...   yield start+(i-start)*step
... 
>>> 
>>> start=3; stop=None; step=2
>>> for i,j in itertools.izip(count(start, step), itertools.islice(range(10), 
>>> start, stop, step)):
...  print i,j
...  
3 3
5 5
7 7
9 9

A "P.S." question for this email is, was there a reason to leave step out of 
itertools.count? 

/c
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to