synchronized enumerate

S

smichr

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.

I posted a very similar item to python-dev, but they said to post it
here. Tutor also said that if anything is to be considered as PEP
worthy, it should be run through here first. So...here goes.

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###

There is a "flexible enumerate()" in the ASPN Cookbook that shows how
to return an arbitrary integer starting point for an iterable,

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/307582

but I would vote against that since enumerate is suppose to give
indices of the original list. What I would like to see supported is
the concept that enumerate should give indices and items from an
iterable--it does right now--but it should also allow you to access a
different portion of the original list and *still* give the indices of
that slice. What I propose is an optional slice argument that would be
used to return the sliced indices and items:

def enum(l, slc=None):
if slc==None: #the usual ennumerate
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) #always give positive indices
yield j, dat
###.... print i, x
....
3 3
4 4
5 5
6 6
7 7.... 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
xrange, islice and izip, but it's more ackward and you have to supply
the same information in two places:

###
aList = range(10).... print i,j
....
2 2
3 3
4 4
5 5
6 6###

It just seems that a function which was suppose to simplify accessing
indices and elements of an iterable should easily allow you to look at
a slice of the iterable and get the same synchronized inidces.

/c
 
A

Antoon Pardon

Op 2005-12-20 said:
What I would like to see supported is
the concept that enumerate should give indices and items from an
iterable--it does right now--but it should also allow you to access a
different portion of the original list and *still* give the indices of
that slice. What I propose is an optional slice argument that would be
used to return the sliced indices and items:

def enum(l, slc=None):
if slc==None: #the usual ennumerate
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) #always give positive indices
yield j, dat
###

The trouble with your suggestion (and the original enumerate,
which you rely on if no slice is provided) is that it doesn't
work as desired if you just give it a sequence that starts
at an other index than zero.

I have a table modules, tables are similar to lists but they
can start at arbitrary indexes. So if I have a table that
goes from -4 to +4, I would like enumerate(tab) or enum(tab)
to give me:

(-4, tab[-4])
(-3, tab[-3])

....

Of course this needs some cooperation from the sequence type.
Personnaly I would have though of a range method on the sequence
which could be used by enumerate to know where to start and end.

I also would prefer the possibilty to use the same notation
as with sequence subscription instead of having to use the
cumbersome slice notation. Something like:

enum(lst, start:start+count)

Instead of

enum(lst, slice(start, start+count))


Of course if you wouldn't mind brackets instead of parenthesis
we could implement enum as a vitual slice, we then would have
to write:

enum[lst, start:start+count]


Just my 2 cents.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top