I want to do a complicated sort: can you do a Schwartzian Transform in Python?
Yes, it's quite simple with list comprehensions.
The technique, attributed to Randal Schwartz of the Perl community, sorts the elements of a list by a metric which maps each element to its "sort value". To sort a list of strings by their uppercase values:
tmp1 = [ (x.upper(), x) for x in L ] # Schwartzian transform
tmp1.sort()
Usorted = [ x[1] for x in tmp1 ]
To sort by the integer value of a subfield extending from positions 10-15 in each string:
tmp2 = [ (int(s[10:15]), s) for s in L ] # Schwartzian transform
tmp2.sort()
Isorted = [ x[1] for x in tmp2 ]
Note that Isorted may also be computed by
def intfield(s):
return int(s[10:15])
def Icmp(s1, s2):
return cmp(intfield(s1), intfield(s2))
Isorted = L[:]
Isorted.sort(Icmp)
but since this method calls intfield() many times for each element of L, it is slower than the Schwartzian Transform.
CATEGORY: programming
last updated 2 years ago by effbot #

With python 2.4 or later the transform could be replaced by:
sorted(L, key=lambda s:s.upper())
or
import string ... sorted(L, key=string.upper)
ErikWilsher 2 years ago #