[2.5.1.1/dictionary] Change sorting order?

John Posner jjposner at optimum.net
Fri Jan 22 15:29:17 EST 2010


On 1/22/2010 7:17 AM, Gilles Ganault wrote:
> Hello
>
> I use a dictionary to keep a list of users connected to a web site.
>
> To avoid users from creating login names that start with digits in
> order to be listed at the top, I'd like to sort the list differently
> every minute so that it'll start with the next letter, eg. display the
> list from A...Zdigits the first time, then B...ZAdigits, etc.
>

I don't believe anyone has suggested customizing the way that the 
dictionary's keys are sorted. How about using a string-like object 
("RotaKey"), with a changeable sort order:

#--------------------------
import string, time

class RotaKey(object):
     """
     string with rotating sort order
     """
     LETTERS = string.ascii_uppercase

     def __init__(self, instring):
         self.string = instring

     @staticmethod
     def RotateSortOrder():
         """
         rotate the letter sequence for sorting RotaKey objects
         """
         RotaKey.LETTERS = RotaKey.LETTERS[1:] + RotaKey.LETTERS[0]

     def __repr__(self): return "<%s>" % self.string

     def __cmp__(self, other):
         self_first, self_rest = self.string[0], self.string[1:]
         other_first, other_rest = other.string[0], other.string[1:]
         result = cmp(self.LETTERS.index(self_first.upper()),
                      self.LETTERS.index(other_first.upper()))
         if result != 0:
             # first letters differ
             return result
         else:
             # first letters same, compare rest of strings
             return cmp(self_rest, other_rest)

if __name__ == "__main__":
     # create dictionary: keys are RotaKey's, values in range 1001 - ...
     names = map(RotaKey,
             "Ant Zebra Bob Cat2 Ant2 Eagle Bob3 Bob2 Cat Dog".split())
     datadict = dict(zip(names, range(1001, 1001+len(names))))

     # TEST: print, rotate, print, rotate, ...
     for i in range(7):
         if i > 0: RotaKey.RotateSortOrder()
         print "=" * 15, i
         for k in sorted(datadict): print k, datadict[k]
#--------------------------

NOTE: I tried implementing RotaKey as a subclass of "str", but found 
that the redefinition of __cmp__() was ignored.

You can invoke RotaKey.RotateSortOrder() every minute (or whatever) to 
change the sort order.

Program output:

=============== 0
<Ant> 1001
<Ant2> 1005
<Bob> 1003
<Bob2> 1008
<Bob3> 1007
<Cat> 1009
<Cat2> 1004
<Dog> 1010
<Eagle> 1006
<Zebra> 1002
=============== 1
<Bob> 1003
<Bob2> 1008
<Bob3> 1007
<Cat> 1009
<Cat2> 1004
<Dog> 1010
<Eagle> 1006
<Zebra> 1002
<Ant> 1001
<Ant2> 1005
=============== 2
<Cat> 1009
<Cat2> 1004
<Dog> 1010
<Eagle> 1006
<Zebra> 1002

  ... etc.

-John



More information about the Python-list mailing list