Say I have a sorted list of strings as in:
[\'A\', \'B\' , \'B1\', \'B11\', \'B2\', \'B21\', \'B22\', \'C\', \'C1\', \'C11\', \'C2\']
Now I wan
Using just key and the precondition that the sequence is already 'sorted':
import re
s = ['A', 'B' , 'B1', 'B11', 'B2', 'B21', 'B22', 'C', 'C1', 'C11', 'C2']
def subgroup_ordinate(element):
# Split the sequence element values into groups and ordinal values.
# use a simple regex and int() in this case
m = re.search('(B)(.+)', element)
if m:
subgroup = m.group(1)
ordinate = int(m.group(2))
else:
subgroup = element
ordinate = None
return (subgroup, ordinate)
print sorted(s, key=subgroup_ordinate)
['A', 'B', 'B1', 'B2', 'B11', 'B21', 'B22', 'C', 'C1', 'C2', 'C11']
The subgroup_ordinate()
function does two things: identifies groups to be sorted and also determines the ordinal number within the groups. This example uses regular expression but the function could be arbitrarily complex. For example we can change it to ur'(B|C)(.+)'
and sort both B and C sequences .
['A', 'B', 'B1', 'B2', 'B11', 'B21', 'B22', 'C', 'C1', 'C2', 'C11']
Reading the bounty question carefully I note the requirement 'sorts some values while leaving others "in place"'. Defining the comparison function to return 0 for elements that are not in subgroups would leave these elements where they were in the sequence.
s2 = ['X', 'B', 'B1', 'B2', 'B11', 'B21', 'A', 'C', 'C1', 'C2', 'C11']
def compare((_a,a),(_b,b)):
return 0 if a is None or b is None else cmp(a,b)
print sorted(s, compare, subgroup_ordinate)
['X', 'B', 'B1', 'B2', 'B11', 'B21', 'A', 'C', 'C1', 'C2', 'C11']