[Python-bugs-list] [ python-Feature Requests-728304 ] reverse form of enumeration

SourceForge.net noreply@sourceforge.net
Mon, 12 May 2003 10:47:25 -0700


Feature Requests item #728304, was opened at 2003-04-27 01:30
Message generated for change (Comment added) made by rhettinger
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=728304&group_id=5470

Category: Python Library
Group: None
>Status: Closed
>Resolution: Rejected
Priority: 5
Submitted By: Douglas Napoleone (derivin)
Assigned to: Nobody/Anonymous (nobody)
Summary: reverse form of enumeration

Initial Comment:
I love the new enumeration builtin. Before it was put in I 
had my own version of the functionality as many did 
using xrange and zip.

I also used an extension that would give a reverse of 
what enumeration returns (in behavior at least)

enumeration(list)
returns an xrange like itterator that behaves like:
( (0, list[0]), (1, list(1)), ...)

my old code looked like:

def old_enumeration( argList):
_ return zip(range(len(argList)), argList)

def revenum( argList ):
_ temp = old_enumeration( argList)
_ temp.reverse()
_ return temp


obviously this is really slow for really long lists and 
tuples

these structures would be used for looping 90% of the 
time. One of my fav's:
matches = []
for ind, val in revenum(aList):
_ if test(val): matches.append(aList.pop(ind))

am I the only person wanting an effecient reverse 
enumeration??

(NOTE: currently if the list is really long I use:
for ind in xrange(len(aList) - 1, -1, -1):
create two new lists, then delete the old one.
the additional time for pop() is non trivial on a list of 
50Mil entries and memory isnt much of a concern as 
time for me. A reverse enumeration would be much 
clearer to read IMO).



----------------------------------------------------------------------

>Comment By: Raymond Hettinger (rhettinger)
Date: 2003-05-12 12:47

Message:
Logged In: YES 
user_id=80475

You were on target with your question about whether 
you're the only one wanting C coded reverse enumeration.  
The use case for going in reverse *and* needing the indices 
is rare.  

When needed, it can be cleanly coded in python in just a 
few lines.  You get reasonable performance with your 
existing code (old_enumeration and revenum). 

Using a generator and an index variable gives an even 
cleaner, memory efficient alternative.  That latter 
approach can be brought to near C speed using just two 
lines from Psyco.

On a separate note, the matches example code suffers 
from O(n^2) run-time because alist.pop(i) has to slide-
back every element after i.  You do *much* better with:  
matches=filter(test, alist) and then alist=filter(inversetest, 
alist).  If test() is expensive, then run a single loop that 
adds each element to either matches or newlist.

Also, if you have 50 Mil entries in your lists (which I find 
surprising with 200Mb for the list of pointers alone and 
much more memory for the objects being pointed to), 
then consider using either Numeric or Pysco to get a 
speed boost.  Failing that, the application may warrant a 
single C function in the time critical section.  Unless both 
the objects and test() are very simple, I would be surprised 
to find the loop overhead to dominate running time.

Also, consider using Py2.3's new itertools module.  You 
ought to get near C speed (as fast as enumerate) from:
  itertools.izip(xrange(len(aList) - 1, -1, -1), alist)

----------------------------------------------------------------------

Comment By: Douglas Napoleone (derivin)
Date: 2003-04-27 21:52

Message:
Logged In: YES 
user_id=541557

At issue is the speed of list operations on excessivly large 
lists. 

a = list(xrange(5000000))    - 1 second
a = list(xrange(50000000))  - 4 min

list(enumerate(a))[::-1]

is 3 list operations... or 12min (actually took 25min for me in 
a test but other processes were running. NOTE: the list
(xrange(#)) time is NOT included in this.)

enumerate(a, reverse=True)  - 15seconds  (took the code for 
enumerate and made my own pyd)

this does not include the time that it would take to make all 
the calls to the enumerate's next() method; obviously.

in the end, quarter of a min, or quarter of an hour. What 
would you use?



----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2003-04-27 12:17

Message:
Logged In: YES 
user_id=80475

This runs pretty fast:

     list(enumerate(data))[::-1]

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=728304&group_id=5470