Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在不使用reverse=True参数的情况下按相反顺序对字符串列表排序?_Python_Python 3.x_String_List_Sorting - Fatal编程技术网

Python 如何在不使用reverse=True参数的情况下按相反顺序对字符串列表排序?

Python 如何在不使用reverse=True参数的情况下按相反顺序对字符串列表排序?,python,python-3.x,string,list,sorting,Python,Python 3.x,String,List,Sorting,我想按相反顺序对字符串列表进行排序,例如: my_list = ['aaa', 'bbb', 'ccc'] 预期结果: ['ccc', 'bbb', 'aaa'] 我不想使用排序(my_list,reverse=True),因为在更复杂的情况下,当按两个值进行过滤时,它将不起作用。例如: my_list2 = [('aaa', 'bbb'), ('aaa', 'ccc'), ('bbb', 'aaa'), ('bbb', 'ccc')] 预期结果将是: [('bbb', 'aaa'), (

我想按相反顺序对字符串列表进行排序,例如:

my_list = ['aaa', 'bbb', 'ccc']
预期结果:

['ccc', 'bbb', 'aaa']
我不想使用排序(my_list,reverse=True),因为在更复杂的情况下,当按两个值进行过滤时,它将不起作用。例如:

my_list2 = [('aaa', 'bbb'), ('aaa', 'ccc'), ('bbb', 'aaa'), ('bbb', 'ccc')]
预期结果将是:

[('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
sorted(my_list2,reverse=True)
返回:

[('bbb', 'ccc'), ('bbb', 'aaa'), ('aaa', 'ccc'), ('aaa', 'bbb')]
数字很简单,你可以取反:

>>> my_list3 = [(1, 2), (1, 3), (2, 1), (2, 3)]
>>> sorted(my_list3, key=lambda x: (-x[0], x[1]))
... [(2, 1), (2, 3), (1, 2), (1, 3)]

但是如何使用字符串呢?

您必须进行两次排序。Python的排序算法是稳定的,这意味着相等的元素保持其相对顺序。使用此选项首先对第二个元素进行排序(按升序排序),然后再次对该输出进行排序,仅对第一个元素按相反顺序进行排序:

sorted(sorted(my_list2, key=lambda t: t[1]), key=lambda t: t[0], reverse=True)
使用而不是
lambda
s可以加快这一点(避免为每个元素返回Python解释器):

演示:

一般规则是从最里面的元素排序到最外面的元素。因此,对于任意元素计数排序,每个排序都有一个键和一个反向布尔值,您可以使用来应用这些:

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))

如果“my_list2”仅包含ASCII,您可以尝试:

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

您可以对值执行负值
ord
,这将适用于ascii字符串:

>>> sorted(my_list2, key=lambda x: ([-ord(l) for l in x[0]], x[1]))
[('bbb', 'aaa'), ('bbb', 'ccc'), ('aaa', 'bbb'), ('aaa', 'ccc')]
对于非ascii,您可以选择如何排序:

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

另一个解决方案是创建一个带有比较函数的类作为键。您只需要定义sort/sorted使用的
\uu\lt\uu

def reverse_key(reverse):
    class C:
        def __init__(self, obj):
            self.obj = obj
        def __lt__(self, other):
            for a, b, r in zip(self.obj, other.obj, reverse):
                if a < b:
                    return not r
                elif a > b:
                    return r
            return False
    return C

如图所示,这只允许调用sort/sorted一次。就性能而言,如果要排序的列表中的每个元组都包含大量项,那么这可能比公认的答案要快。

你能解释一下
[('aaa','bbb'),('aaa','ccc'),('bbb','ccc'),('bbb','aaa'),('bbb','ccc'),('aaa','bbb'),('aaa','ccc'),('aaa','ccc'),
是如何结束的吗?@deveshkumarsing外部或第一个项目是降序的,内部项目是升序的。@deveshkumarsing:按降序排列的第一个元素(
'bbb'
之前的
'aaa'
),然后在第一个元素相等的元素之间,按升序排列的第二个元素(对于第一个元素为
'bbb'
'aaa'
排序在
'ccc'
之前的元组)。如果我需要按两个以上的值进行排序,该怎么办?一行代码看起来不可读。你能提供一个例子,排序是在不同的代码行中进行的吗?这是一个多么好的答案@MartijnPieters!在我的生活中从来没有想到过这一点!很好的方法,但在我的例子中,字符串是UTF-8编码的,并且包含非ASCII字符。将在希望检查
-ord(c)
是否涵盖UTF-8的所有情况。@niekas您是对的。它必须涵盖,因为“字符串的字典排序使用Unicode代码点…”,而255在我的代码中是不必要的。
>>> sorted(my_list2, key=lambda x: ([-ord(l) for l in x[0]], x[1]))
[('ébb', 'écc'), ('bbb', 'aaa'), ('aaa', 'bbb'), ('aaa', 'ccc')]
def reverse_key(reverse):
    class C:
        def __init__(self, obj):
            self.obj = obj
        def __lt__(self, other):
            for a, b, r in zip(self.obj, other.obj, reverse):
                if a < b:
                    return not r
                elif a > b:
                    return r
            return False
    return C
my_list2 = [('aaa', 'bbb'), ('aaa', 'ccc'), ('bbb', 'aaa'), ('bbb', 'ccc')]
sorted(my_list2, key=reverse_key([True, False]))