[2.5.1.1/dictionary] Change sorting order?

Jan Kaliszewski zuo at chopin.edu.pl
Fri Jan 22 15:44:28 CET 2010


22-01-2010 Steven D'Aprano <steve at remove-this-cybersource.com.au> wrote:

> On Fri, 22 Jan 2010 13:17:44 +0100, Gilles Ganault wrote:

>> 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.
>>
>> That way, users have no incentive to create login names that start with
>> either a digit or letter A.
>
> If you want to prohibit users from starting their login names with a
> digit, prohibit them from creating a login name with a digit.

I understand that a real problem is to make all names -- regardless of  
characters they are made of -- having "the equal rights" in terms of  
visibility.

>> I see that dictionaries can be sorted using the... sort() method

List, not dictionaries (they have nothing to do with the matter).

>> but is it possible to have Python start sorting from a different
>> letter?
>
> You can write a customer sort routine by using the key parameter to sort,
> which will probably be messy.

It could be done e.g. in such a way:

      # (for Python 2.x)
      from collections import deque
      import string

      CHARS = string.ascii_lowercase + string.digits
      def rotated_key(rotated_chars=deque(CHARS)):
          rotated_chars.rotate(1)
          tr_table = string.maketrans(CHARS, ''.join(rotated_chars))
          def key(item):
              return item.translate(tr_table)
          return key

      # generate some names
      import random
      users = [''.join(random.choice(CHARS) for i in xrange(3))
               for j in xrange(50)]

      for i in xrange(50):
          users.sort(key=rotated_key())
          print ','.join(users)
          print

But it still doesn't guarantee real "equal rights in visibility" (holders
of names starting with rarely used characters are in better situation).

> What I'd do is keep 27 lists of user names,
> according to the first letter (26 letters from A to Z, plus one extra):

> users = [  # keep separate lists for each starting letter
>     ['aaron', 'avril', 'adam'],
>     ['betty', 'bob'],
>     ['craig', 'cathy'],
>     ['danni', 'da5id', 'donna'],
>     # ... and so on
>     ['zoe', 'zach'],
>     ['4dam', '1-4m-t00-c001']
>     ]

But here the second letter becomes important for "visibility" and users
still are not equal.

And all this mess in unnecessary, because there is one perfect and simple
solution -- see the Neil Cerutti's post.

22-01-2010, 14:58:58 Gilles Ganault <nospam at nospam.com> wrote:

> On 22 Jan 2010 13:35:26 GMT, Neil Cerutti <neilc at norwich.edu> wrote:
>> Resorting is more work than is needed. Just choose a different
>> starting index each time you display the names, and set up your
>> lister to wrap-around to your arbitrary starting index.
>
> Thanks. In this case, it means that in each loop iteration, I must
> search the list to find which item starts with the letter I'd like to
> begin sorting, eg. "B". Does Python include a search method or do I
> have to use a for loop to locate this starting item?

There is e.g. `bisect' module -- you can search as well as insert with
its functions. But IMHO you shouldn't search for the next starting
*letter*, but for the next *name* in the list (basing on name that was
used recently).

If the list were immutable, no searching would be needed (indexes would
be sufficient), but in real life users can be added and deleted in the
meantime (so index of a particular name changes).

Regards,

*j

-- 
Jan Kaliszewski (zuo) <zuo at chopin.edu.pl>



More information about the Python-list mailing list