Is there a more elegant way to do this?

Alex Martelli aleaxit at yahoo.com
Wed Sep 13 18:08:24 EDT 2000


"Aahz Maruch" <aahz at panix.com> wrote in message
news:8poiii$999$1 at panix3.panix.com...
> In article <8poglt$10fq$1 at news.rchland.ibm.com>,
> Larry Whitley <ldw at us.ibm.com> wrote:
> >
> >I have a list of counters that will have a wide variety of different
values
> >in them.  At intervals while the program runs, I will print out the
indexes
> >of the counters with the five largest counts.  The counters are in a list
    [snip]
> def runningReport(self, numItems=5): # a method of a larger class
>     if numItems > len(self.counter):
>         numItems = len(self.counter)
>     numItems = -1 * abs(int(numItems)) # make sure numItems is negative
int
>     temp = self.counters[:] #make copy of self.counters
>     temp.sort()
>     temp2 = temp[numItems:] #negative numItems pulls from end of list
>     temp2.reverse() #Change to descending order?
>     print temp2

It seems to me that you're printing the VALUES, not the INDEXES,
of the five largest counters.  Printing the indexes was the request.

The basic approach I would suggest: first, place in temp a list of
PAIRS (countervalue,counterindex); then, sort (on countervalue);
the, for the last numItems items, print the second of each pair.

For the first step, in classic Python (up to 1.6) I suggest:
    temp = map(None, self.counters, range(len(self.counters)))
while in Python 2 I would prefer the slightly more elegant:
    temp = zip(self.counters, range(len(self.counters)))
or the more-elegant-yet:
    temp = zip(self.counters, integers())
having previously defined:
class integers:
    def __getitem__(self,i):
        return i
which relies on zip's defined semantics (stops when the
shortest of the sequences passed to it ends, so the others
can be "lazy" infinite streams...) -- wouldn't work with
map (which gives as many tuples as the _longest_ of the
sequences it's passed, so, no lazy infinite streams there!).

The second step is clearly
    temp.sort()

To get the second item of each of numItems pairs you
have several approaches.  In classic Python, for example:
    for i in range(numItems):
        print temp[-i-1][1],
    print
In Python 2, you might prefer, with numItems<0...:
    temp2 = [y for x,y in temp[numItems:]]
    temp2.reverse()
    print temp2
Or, of course, several possible mixes and variations.


But the key idea, I think, is the zipping of counter values
with counter indices, and the unzipping after the sort.


Alex







More information about the Python-list mailing list