How to sort a list of strings in reverse order without using reverse=True parameter?

前端 未结 3 1656
面向向阳花
面向向阳花 2020-12-21 08:19

I want to sort a list of strings in reverse order, e.g.:

my_list = [\'aaa\', \'bbb\', \'ccc\']

expected result:

[\'ccc\', \         


        
相关标签:
3条回答
  • 2020-12-21 08:26

    You'll have to sort twice. Python's sort algorithm is stable, which means that elements that are equal keep their relative order. Use this to first sort on the second element (sorting in ascending order), then sort that output again, on only the first element and in reverse order:

    sorted(sorted(my_list2, key=lambda t: t[1]), key=lambda t: t[0], reverse=True)
    

    Using operator.itemgetter() instead of lambdas can make this little bit faster (avoiding stepping back in to the Python interpreter for each element):

    from operator import itemgetter
    
    sorted(sorted(my_list2, key=itemgetter(1)), key=itemgetter(0), reverse=True)
    

    Demo:

    >>> from operator import itemgetter
    >>> my_list2 = [('aaa', 'bbb'), ('aaa', 'ccc'), ('bbb', 'aaa'), ('bbb', 'ccc')]
    >>> sorted(sorted(my_list2, key=lambda t: t[1]), key=lambda t: t[0], reverse=True)
    [('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
    >>> sorted(sorted(my_list2, key=itemgetter(1)), key=itemgetter(0), reverse=True)
    [('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
    

    The general rule is to sort from the innermost element to the outermost element. So for an arbitrary-element-count sort, with a key and a reverse boolean each, you can use the functools.reduce() function to apply these:

    from functools import reduce
    from operator import itemgetter
    
    def sort_multiple(sequence, *sort_order):
        """Sort a sequence by multiple criteria.
    
        Accepts a sequence and 0 or more (key, reverse) tuples, where
        the key is a callable used to extract the value to sort on
        from the input sequence, and reverse is a boolean dictating if
        this value is sorted in ascending or descending order.
    
        """
        return reduce(
            lambda s, order: sorted(s, key=order[0], reverse=order[1]),
            reversed(sort_order),
            sequence
        )
    
    sort_multiple(my_list2, (itemgetter(0), True), (itemgetter(1), False))
    
    0 讨论(0)
  • 2020-12-21 08:37

    You can do a negative ord on the value and that would work for an ascii string:

    >>> sorted(my_list2, key=lambda x: ([-ord(l) for l in x[0]], x[1]))
    [('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
    

    For non-ascii though you'd have choices in how you'd want to sort though:

    >>> sorted(my_list2, key=lambda x: ([-ord(l) for l in x[0]], x[1]))
    [('ébb', 'écc'), ('bbb', 'aaa'), ('aaa', 'bbb'), ('aaa', 'ccc')]
    
    0 讨论(0)
  • 2020-12-21 08:49

    If 'my_list2' contains only ASCII, you can try:

    sorted(my_list2, key=lambda t: (t[0],[255-ord(c) for c in list(t[1])]), reverse=True)                                
    [('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
    
    0 讨论(0)
提交回复
热议问题