使用两个键排序Python列表,但只有一个按相反顺序排序

Sta*_*ądź 9 python sorting tuples key

我想知道用两个键对元组列表进行排序的Pythonic方法是什么,其中用一个(并且只有一个)键进行排序将是相反的顺序,而用另一个键进行排序将不区分大小写.更具体地说,我有一个包含元组的列表:

myList = [(ele1A, ele2A),(ele1B, ele2B),(ele1C, ele2C)]
Run Code Online (Sandbox Code Playgroud)

我可以使用以下代码用两个键对其进行排序:

sortedList = sorted(myList, key = lambda y: (y[0].lower(), y[1]))
Run Code Online (Sandbox Code Playgroud)

要按相反顺序排序,我可以使用

sortedList = sorted(myList, key = lambda y: (y[0].lower(), y[1]), reverse = True)
Run Code Online (Sandbox Code Playgroud)

但这会按两个键的相反顺序排序.

任何提示都非常感谢.

bla*_*nda 21

一种方法是创建一个反向器类并使用它来装饰有问题的键。此类可用于反转任何可比较的字段。

class reversor:
    def __init__(self, obj):
        self.obj = obj

    def __eq__(self, other):
        return other.obj == self.obj

    def __lt__(self, other):
        return other.obj < self.obj
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

sortedList = sorted(myList, key=lambda(y): (y[0].lower(), reversor(y[1]))
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案可与字符串或其他对象一起使用。它是一种比标记为最佳解决方案更干净的解决方案。 (5认同)
  • 总排序不需要用作排序函数中的关键参数。你只需要 == 和 &lt; (2认同)

小智 16

当我们需要按照两个约束对列表进行排序时,将使用两个键,一个按升序排序,另一个按降序排列在同一个列表中或任何
在您的示例
sortedList = sorted(myList, key = lambda y: (y[0].lower(), y[1]))中只能按一个顺序对整个列表进行排序,
您可以尝试这些并查看发生的情况

sortedList = sorted(myList, key = lambda y: (y[0].lower(), -y[1]))
sortedList = sorted(myList, key = lambda y: (-y[0].lower(), y[1]))
sortedList = sorted(myList, key = lambda y: (-y[0].lower(), -y[1]))
Run Code Online (Sandbox Code Playgroud)

希望你能在此之后理解;)

  • 这仅适用于数字列表?OP 没有说明元素是什么类型。 (12认同)
  • @black-panda 的答案适用于所有数据类型 - 以及可比较的对象类型 - 并且是一个更好的答案。 (3认同)

Tim*_*inn 6

在使用 Python 3 时,@KellyBundy做了一个很好的观察,即当前python 文档中列出的多重排序方法非常快,并且可用于完成具有离散排序的多列排序。这是一个NoneType安全版本:

students = [
     {'idx': 0, 'name': 'john', 'grade': 'A', 'attend': 100}
    ,{'idx': 1, 'name': 'jane', 'grade': 'B', 'attend': 80}
    ,{'idx': 2, 'name': 'dave', 'grade': 'B', 'attend': 85}
    ,{'idx': 3, 'name': 'stu' , 'grade': None, 'attend': 85}
]

def key_grade(student):
    grade = student['grade']
    return grade is None, grade
def key_attend(student):
    attend = student['attend']
    return attend is None, attend
students_sorted = sorted(students, key=key_attend)
students_sorted.sort(key=key_grade, reverse=True)
Run Code Online (Sandbox Code Playgroud)

笔记:

  • <variable> 为 None,检查是防御性检查,以便搜索不会在 None 值上失败
  • 虽然,这会执行多次排序调用,但它无疑是最快的多重排序方法!

我创建了一个名为multisort的新 Python 项目,它公开了三种方法:

方法 描述 笔记 速度
多分类 根据 python 文档的示例设计的简单单行代码multisort 其中第二快,但最可配置且易于阅读。 0.0035
cmp_函数 模型中的多列排序java.util.Comparator 合理的速度 0.0138
逆转子 反转器的实现 - 参见Black Panda的回答 相当慢的方法 0.0370

以供参考:

方法 速度
凯莉邦迪的多重分类 0.0005
熊猫 0.0079

注意:速度是 1000 行 4 列运行 10 次的平均值。

multisort来自multisort 图书馆的示例:

from multisort import multisort
rows_sorted = multisort(rows_dict, [
        ('grade', True, lambda s:None if s is None else s.upper()),
        'attend',
], reverse=True)
Run Code Online (Sandbox Code Playgroud)

然而,对于来自 Java 的开发人员来说,这里有一个类似于java.util.ComparatorPython 3 中使用的示例:

from multisort import cmp_func

def cmp_student(a,b):
    k='grade'; va=a[k]; vb=b[k]
    if va != vb:
        if va is None: return -1
        if vb is None: return 1
        return -1 if va > vb else 1
    k='attend'; va=a[k]; vb=b[k]; 
    if va != vb:
        return -1 if va < vb else 1
    return 0

students_sorted = sorted(students, key=cmp_func(cmp_student))
Run Code Online (Sandbox Code Playgroud)