• 关于Python的多重排序


    Python预置的list.sort()、sorted()方法可实现各种数组的排序,但支持的只限于一个key,如果要多重排序,目前所知的方法只有自定义了。

    Help on built-in function sorted in module __builtin__:

    sorted(...)

        sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list

    查看sorted的帮助可知,cmp参数在第二个位置,不过一般都以kwargs的形式显式写出。

    关于cmp,cmp定义的函数接收源数组中相邻的两个元素,在比较大小后分别返回负值、0或正值,分别代表第一个值小于、等于或大于第二个值,然后再按照key和reverse的设定去进行排序。

    >>> a=list(range(10))
    >>> a.reverse()    # reverse为on place方法
    >>> a
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    >>> a.sort(cmp=lambda a,b: a-b)    # a-b < 0  默认reverse为False,升顺排序,结果为正常顺序
    >>> a
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> a.sort(cmp=lambda a,b: b-a)    # b-a > 0  lambda返回正值,认为a > b,按照“升顺”排序,实际结果为降序
    >>> a                              # sort同样是on place方法
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    >>> 

    对于多重排序,可利用cmp方法,分别定义key的优先级,以及排序方式,达到多重、独立顺序的排序方式实现。

    代码如下:

    d1 = {1:23, 'b': 62}
    d2 = {1:24, 'b': 2}
    d3 = {1:23, 'b': 54}
    d4 = {1:23, 'b': 1}
    d5 = {1:01, 'b': 9}
    d6 = {1:23, 'b': 32}
    d7 = {1:05, 'b': 33}
    d8 = {1:39, 'b': 100}
    
    li = [d1, d2, d3, d4, d5, d6, d7, d8]
    
    def cmpf(a, b, key1, key2):
         if (a[key1] != b[key1]):
                 return a[key1] - b[key1]
         else:
                 return a[key2] - b[key2]
    
    def rcmpf(a, b, key1, key2):
         if (a[key1] != b[key1]):
                 return b[key1] - a[key1]
         else:
                 return a[key2] - b[key2]
    
    # key1、key2均为升序
    sorted(li, cmp=lambda a,b: cmpf(a, b, 1, 'b'))
    
    # key1降序、key2升序
    sorted(li, cmp=lambda a,b: rcmpf(a, b, 1, 'b'))

    执行结果如下:

    >>> sorted(li, cmp=lambda a,b: cmpf(a, b, 1, 'b'))
    [{1: 1, 'b': 9}, {1: 5, 'b': 33}, {1: 23, 'b': 1}, {1: 23, 'b': 32}, {1: 23, 'b': 54}, {1: 23, 'b': 62}, {1: 24, 'b': 2}, {1: 39, 'b': 100}]
    >>> 
    >>> sorted(li, cmp=lambda a,b: rcmpf(a, b, 1, 'b'))
    [{1: 39, 'b': 100}, {1: 24, 'b': 2}, {1: 23, 'b': 1}, {1: 23, 'b': 32}, {1: 23, 'b': 54}, {1: 23, 'b': 62}, {1: 5, 'b': 33}, {1: 1, 'b': 9}]
    >>> 

    可以看到混合排序结果正常。

    PS:按照预想,这种方式应该适用于所有可以指定多个key的数据结构,不过仍待验证。

    对于Python3,sort方法取消了cmp参数,官方给出的解决方案是进行多次排序,优先级低的字段先排序,然后逐个根据优先级高的字段排序

    >>> d1 = {1:23, 'b': 62}
    >>> d2 = {1:24, 'b': 2}
    >>> d3 = {1:23, 'b': 54}
    >>> d4 = {1:23, 'b': 1}
    >>> d5 = {1:1, 'b': 9}
    >>> d6 = {1:23, 'b': 32}
    >>> d7 = {1:5, 'b': 33}
    >>> d8 = {1:39, 'b': 100}
    >>> li = [d1, d2, d3, d4, d5, d6, d7, d8]
    >>> li.sort(key=lambda e: e['b'])  # 现根据'b'进行排序,优先级较低
    >>> pprint(li)
    [{1: 23, 'b': 1},
     {1: 24, 'b': 2},
     {1: 1, 'b': 9},
     {1: 23, 'b': 32},
     {1: 5, 'b': 33},
     {1: 23, 'b': 54},
     {1: 23, 'b': 62},
     {1: 39, 'b': 100}]
    >>> li.sort(key=lambda e: e[1])  # 再根据1进行排序,优先级高于'b'
    >>> pprint(li)
    [{1: 1, 'b': 9},
     {1: 5, 'b': 33},
     {1: 23, 'b': 1},
     {1: 23, 'b': 32},
     {1: 23, 'b': 54},
     {1: 23, 'b': 62},
     {1: 24, 'b': 2},
     {1: 39, 'b': 100}]
    >>> 
  • 相关阅读:
    为了你,我一定要写诗
    哈佛成功金句25则(看一遍,都会很有收获!)
    成功者的十三个“百万元习惯”
    商业领袖的7大人脉宝典
    我为你疯狂
    秋收,为何我收获的只有泪水
    又逢中秋月
    今宵谁与共
    26句话,让你豁然开朗
    田彩蝶(帮别人名字作诗)
  • 原文地址:https://www.cnblogs.com/harelion/p/4934407.html
Copyright © 2020-2023  润新知