我试图复制(如果可能改善)的Python 2.x的在3.x的排序行为,使双方订购类型喜欢int,float等如预期进行排序,并相互unorderable类型的输出中进行分组。
int
float
这是我正在谈论的示例:
>>> sorted([0, 'one', 2.3, 'four', -5]) # Python 2.x [-5, 0, 2.3, 'four', 'one'] >>> sorted([0, 'one', 2.3, 'four', -5]) # Python 3.x Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: str() < int()
我之前在此方面的尝试(使用键参数的类)sorted()从根本上被破坏了,因为它的方法是
sorted()
正如布伦·巴恩(BrenBarn)的出色回答所解释的那样,这可能导致不及物动词的排序。
我最初拒绝甚至不尝试编写代码的简单方法是使用返回(type, value)元组的键函数:
(type, value)
def motley(value): return repr(type(value)), value
但是,这不能满足我的要求。首先,它打破了相互可排序类型的自然排序:
>>> sorted([0, 123.4, 5, -6, 7.89]) [-6, 0, 5, 7.89, 123.4] >>> sorted([0, 123.4, 5, -6, 7.89], key=motley) [7.89, 123.4, -6, 0, 5]
其次,当输入包含两个本质上不可排序的对象时,它将引发异常:
>>> sorted([{1:2}, {3:4}], key=motley) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: dict() < dict()
…这当然是Python 2.x和3.x的标准行为- 但理想情况下,我希望将这些类型组合在一起(我并不特别在意它们的顺序,但似乎与之保持一致Python保证稳定排序,确保它们保留原始顺序。
我可以通过特殊包装解决数字类型的第一个问题:
from numbers import Real from decimal import Decimal def motley(value): numeric = Real, Decimal if isinstance(value, numeric): typeinfo = numeric else: typeinfo = type(value) return repr(typeinfo), value
…一直有效:
>>> sorted([0, 'one', 2.3, 'four', -5], key=motley) [-5, 0, 2.3, 'four', 'one']
…但是没有考虑到可能存在其他相互区分的(可能是用户定义的)不同类型的事实,当然,对于本质上不可排序的类型,仍然会失败:
是否有其他方法解决了 两个 任意的,不同的,但是,相互订购类型的问题 ,并 认为本质unorderable类型的?
愚蠢的想法:首先将所有不同的项目划分为可以相互比较的组,对各个组进行排序,最后将它们连接起来。我假设某项目与某组的第一个成员具有可比性,那么该项目可与该组的所有成员具有可比性。像这样的东西(Python3):
import itertools def python2sort(x): it = iter(x) groups = [[next(it)]] for item in it: for group in groups: try: item < group[0] # exception if not comparable group.append(item) break except TypeError: continue else: # did not break, make new group groups.append([item]) print(groups) # for debugging return itertools.chain.from_iterable(sorted(group) for group in groups)
在可悲的情况下,这将是二次运行时间,所有项目都不具有可比性,但是我想唯一确定的方法是检查所有可能的组合。对于试图对一长串无法排序的项(例如复数)进行排序的人,将二次行为视为应受的惩罚。在一些字符串和一些整数混合的更常见情况下,速度应类似于普通排序的速度。快速测试:
In [19]: x = [0, 'one', 2.3, 'four', -5, 1j, 2j, -5.5, 13 , 15.3, 'aa', 'zz'] In [20]: list(python2sort(x)) [[0, 2.3, -5, -5.5, 13, 15.3], ['one', 'four', 'aa', 'zz'], [1j], [2j]] Out[20]: [-5.5, -5, 0, 2.3, 13, 15.3, 'aa', 'four', 'one', 'zz', 1j, 2j]
这似乎也是一种“稳定的排序”,因为这些组是按照遇到无与伦比的项目的顺序形成的。