我想知道用两个键对元组列表进行排序的Python方法是什么,其中用一个键(并且只有一个键)排序将是逆序的,而用另一个键排序将不区分大小写。更具体地说,我有一个包含如下元组的列表:
myList = [(ele1A, ele2A),(ele1B, ele2B),(ele1C, ele2C)]
我可以使用下面的代码用两个键对它进行排序:
sortedList = sorted(myList, key = lambda y: (y[0].lower(), y[1]))
要按逆序排序,我可以使用
sortedList = sorted(myList, key = lambda y: (y[0].lower(), y[1]), reverse = True)
但是这将用两个键以相反的顺序排序。
8条答案
按热度按时间mzsu5hc01#
当我们需要对一个有两个约束的列表进行排序时,将使用两个键:一个按升序排列,另一个按降序排列,在同一列表或任何
在你的例子中,
你可以排序整个列表只在一个顺序.
您可以尝试以下方法并检查发生了什么:
csga3l582#
你可以创建一个reversor类,用它来修饰所讨论的键,这个类可以用来反转任何可比较的字段。
像这样使用它:
wn9m85ua3#
有时候除了使用比较器函数之外,几乎没有别的选择。在Python 2.4的介绍中,
sorted
有一个cmp
参数,但是为了使用更高效的key
函数,这个参数从Python 3中被删除了。在Python 3.2中,cmp_to_key
被添加到functools
中;它通过将原始对象 Package 在一个对象中来创建键,该对象的比较函数基于cmp
函数。(您可以在SortingHow-To的末尾看到cmp_to_key
的简单定义在您的情况下,由于小写相对昂贵,您可能希望组合使用:
hfyxw5xn4#
方法1
一个简单但可能不是最有效的解决方案是两次排序:第一次使用第二元素,第二次使用第一元素:
或分解:
方法二
如果你的元素是数字,你可以稍微作弊一下:
方法3
cmp
关键字在Python 3中不可用。*另一种方法是在比较元素时交换元素:
或者,使用lambda来避免编写函数:
umuewwlo5#
在使用Python 3的时候,@KellyBundy做了一个很好的观察,在当前的Python文档中列出的multisort方法非常快,可以用来完成离散排序的多列排序,下面是
NoneType
安全版本:注:
我创建了一个新的Python项目multisort,它公开了三种方法:
| 方法|描述|附注|速率|
| - ------|- ------|- ------|- ------|
| 多分类|根据python文档中的
multisort
示例设计的简单一行程序|第二快的一堆,但最可配置和易于阅读。|0.0035分|| cmp_函数|模型
java.util.Comparator
中的多列排序|合理速度|零点零一三八|| 反向器|反向器的实现-参见Black Panda的答案|方法相当缓慢|0.0370|
供参考:
| 方法|速率|
| - ------|- ------|
| KellyBundy多重排序|0.0005分|
| Pandas|0.0079|
注:速度是1000行4列10次运行的平均值。
来自
multisort
library的multisort
示例:然而,对于来自Java的开发人员来说,这里有一个类似于
java.util.Comparator
的例子,可以在Python 3中使用:xdyibdwo6#
也许是优雅但不是有效的方式:
carvr3hs7#
至少在我的例子中,使用不同的参数调用
X.sort()
两次是可能的,一次是相反的,另一次不是。我所要做的就是注意排序的优先级, -最后进行优先级较高的排序。举个例子,我有一个字符串列表,我想按长度从长到短排序,如果字符串长度相同,再按字母顺序排序。
翻译过来就是:
o3imoua48#
基本理论
以下所有内容都适用于内置的
sorted
函数和列表的.sort
方法。一般来说,一个
key
排序函数可以简单地生成一个元组,其中每个元素对应一个我们想要用来排序的“键”,这些元组将是sort lexicographically,所以这会生成想要的结果--元素根据第一个键结果排序,第二个键结果打破平局,等等。同时,用于排序的
reverse
关键字参数可以指定按逆序排序,这相当于正常排序,然后将结果反转,但效率更高。但是,此
reverse
设置适用于整个排序。它不允许先按一个键升序排序,然后按另一个键降序排序,反之亦然。示例设置
可以对包含任何类型对象的列表进行排序,而不仅仅是嵌套列表/元组;并且可以编写以任何方式处理这些对象的关键函数-例如,编写到sort instances of a class according to the value of a specific attribute。为了清楚起见(即,为了使用属性名称),我将设置一个简单的
namedtuple
并演示排序示例列表的技术。特殊情况:按两个数字键排序
要模拟反向排序,取一个数值的负数就足够了。
特殊情况:最多按一个非数字键排序
如果只有一个非数字键,选择是否使用
reverse
可以避免这样的问题,即只有数字键可以取反:使用 Package 对值求反
一个更通用的方法是创建一个 Package 类
negated
,语义为negated(x) < negated(y)
当且仅当x >= y
。这是in black panda's answer所采用的方法。因此:更复杂:调整函数而不是值
假设已有某个键函数
my_key
,我们想先按其结果降序排序,再按其他键升序排序,我们不需要重写my_key
,可以这样修改它:因为
negated_result
接受一个函数并返回一个函数,所以它也可以用作装饰器。如果所有其他方法都失败:按键重复排序
由于Python的内置排序是guaranteed stable,我们可以简单地对第二个键排序,然后对第一个键排序:
其思想是在应用主排序时保留子排序。记住以相反顺序执行此操作有点棘手,因此可能需要一个 Package 函数。例如: