Sort a sublist of elements in a list leaving the rest in place

前端 未结 15 2298
小蘑菇
小蘑菇 2021-02-13 14:28

Say I have a sorted list of strings as in:

[\'A\', \'B\' , \'B1\', \'B11\', \'B2\', \'B21\', \'B22\', \'C\', \'C1\', \'C11\', \'C2\']

Now I wan

15条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-13 15:08

    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']
    

提交回复
热议问题