Flexable Collating (feedback please)

Ron Adam rrr at ronadam.com
Wed Oct 18 18:17:57 EDT 2006



This is how I changed it...

(I edited out the test and imports for posting here.)



locale.setlocale(locale.LC_ALL, '')  # use current locale settings

class Collate(object):
     """ A general purpose and configurable collator class.
     """
     options = [ 'CAPS_FIRST', 'NUMERICAL', 'HYPHEN_AS_SPACE',
                 'UNDERSCORE_AS_SPACE', 'IGNORE_LEADING_WS',
                 'IGNORE_COMMAS', 'PERIOD_AS_COMMAS' ]

     def __init__(self, flags=""):
         if flags:
             flags = flags.upper().split()
             for value in flags:
                 if value not in self.options:
                     raise ValueError, 'Invalid option: %s' % value
             self.txtable = []
             if 'HYPHEN_AS_SPACE' in flags:
                 self.txtable.append(('-', ' '))
             if 'UNDERSCORE_AS_SPACE' in flags:
                 self.txtable.append(('_', ' '))
             if 'PERIOD_AS_COMMAS' in flags:
                 self.txtable.append(('.', ','))
             if 'IGNORE_COMMAS' in flags:
                 self.txtable.append((',', ''))
         self.flags = flags
         self.numrex = re.compile(r'([\d\.]*|\D*)', re.LOCALE)

     def transform(self, s):
         """ Transform a string for collating.
         """
         if not self.flags:
             return locale.strxfrm(s)
         for a, b in self.txtable:
             s = s.replace(a, b)
         if 'IGNORE_LEADING_WS' in self.flags:
             s = s.strip()
         if 'CAPS_FIRST' in self.flags:
             s = s.swapcase()
         if 'NUMERICAL' in self.flags:
             slist = self.numrex.split(s)
             for i, x in enumerate(slist):
                 try:
                     slist[i] = float(x)
                 except:
                     slist[i] = locale.strxfrm(x)
             return slist
         return locale.strxfrm(s)

     def __call__(self, a):
         """ This allows the Collate class to be used as a sort key.

                 USE: list.sort(key=Collate(flags))
         """
         return self.transform(a)

def collate(slist, flags=[]):
     """ Collate list of strings in place.
     """
     slist.sort(key=Collate(flags).transform)

def collated(slist, flags=[]):
     """ Return a collated list of strings.
     """
     return sorted(slist, key=Collate(flags).transform)




More information about the Python-list mailing list