Python3中混合数据类型的深层嵌套列表的字典排序

Python3中混合数据类型的深层嵌套列表的字典排序,python,list,sorting,python-3.x,comparison,Python,List,Sorting,Python 3.x,Comparison,在Python3中,list.sort()方法将进行字典排序。但在Python 3中,将列表与浮点值或int进行比较会抛出TypeError,而在Python 2中,您可以这样做: >>> [0, 1] < 2 False 结果应该是False,因为a[0][0]是一个列表,b[0][0]是一个int,在我的情况下,ints应该总是被认为小于列表 编辑: 我希望实现一个与内置Python 3列表相同的排序函数。排序,除非将列表与浮点或int进行比较,在这种情况下,列表应

在Python3中,
list.sort()
方法将进行字典排序。但在Python 3中,将列表与
浮点值
int
进行比较会抛出
TypeError
,而在Python 2中,您可以这样做:

>>> [0, 1] < 2
False
结果应该是
False
,因为
a[0][0]
是一个
列表
b[0][0]
是一个
int
,在我的情况下,
int
s应该总是被认为小于
列表

编辑:
我希望实现一个与内置Python 3
列表相同的排序函数。排序
,除非将
列表
浮点
int
进行比较,在这种情况下,
列表
应该始终被认为更大。

正确的解决方案不是将
列表
子类化,但只是为了:

custom\u key\u函数(list\u元素)
应该为该列表元素生成一个标准化键,所有键都属于同一类

在不知道列表可能包含哪些类型的元素的情况下,我不会进一步推测如何实现它,但我认为从您的示例中可以公平地说,您可能需要使用相同的
自定义键函数递归地对子列表排序,因为:

大多数其他内置类型的对象比较不相等,除非 同一对象;选择是否将一个对象视为较小的对象 或比另一个更大,是任意制造的,但在内部一致 程序的一次执行

只有当两个对象属于同一类型时,对象比较才有意义。不应该在程序中依赖表达式(如
[0,1]<2
)返回的值,这就是为什么从Python 3中删除此行为的原因

为了进一步解释,如果您有列表
[[[0,1],[2,3],[0,1]]
,那么它有两个元素:
[[0,1],[2,3]]和[0,1]
。为了让python对它们进行排序,它会按字典顺序比较它们的内部值,因为它们都是列表,第一个值为
[0,1]和[2,3]
,第二个值为
0和1
。但是,它必须将
[0,1]与类型不同的0
进行比较,因此,比较会产生任意结果

因此,此排序被破坏。

如上所述,如果您有一些列表可以进行有意义的排序,而有些列表不能(由于上述解释),一个简单的解决方案是捕获可能的异常,然后返回False

try:
    [0, 1] < 2
except TypeError:
    # return or assign False. True is not actually meaningful.
如果您想要产生一个有意义的排序(如果这实际上是有意义的),那么您必须定义一个键函数,正如前面提到的。不过,这可能相当复杂。也许从不同的角度看待你的问题会更好。

这里有一个缓慢的方法

要在不可比较的类型
A
B
之间添加顺序,请将它们的实例放在元组中:

a = [[[0, 1], [2, 3]], [0, 1]]
b = [[0, 1], [2, 3]]

def deep_annotate(item):
    if isinstance(item, list):
        return (1, [deep_annotate(i) for i in item])
    else:
        return (0, item)

deep_annotate(a) < deep_annotate(b)
#>>> False

deep_annotate(a) > deep_annotate(b)
#>>> True
a=[[0,1],[2,3],[0,1]]
b=[[0,1],[2,3]]
def深度注释(项目):
如果存在(项目、列表):
返回(1,[项目中i的深注释(i)])
其他:
返回(0,项目)
深度注释(a)<深度注释(b)
#>>>假的
深度注释(a)>深度注释(b)
#>>>真的

不幸的是,这其中很多都不是捷径,可以通过巧妙地使用
cmp\u to\u键

来实现。你知道python2比较几乎毫无意义吗?所有
list
s大于所有
int
s,因为
l
i
之后。。。你真的需要这种排序吗?正如已经说过的,这种排序的比较是没有意义的。您到底想比较什么(所有元素的总和、元素的数量、嵌套的深度)?换句话说,为了你的目的,第一个列表的什么属性使得它比第二个列表更大?@SiHa,在我的edit.Hmm中澄清了一些事情。正如Dan所说,棘手的一点是编写一个返回相同类型的键函数,而不管它是用
int
float
还是
list
调用的,它也将正确地将
list
作为
int
进行计算,并且仍然适用于“正常”比较(9>3,b>a)我的问题出现在将列表呈现为一种特殊的“标准形式”的过程中;为了这个目的,不管是什么内容,只要考虑一个<代码> int <代码>或<代码>浮点总是小于列表。不同类型的对象可以进行有意义的比较,只要比较是明确定义的,我刚才描述的关系就是这样。好的,我正在考虑一个解决方案。这个表格还有什么结构可以帮助我们吗?深度有限制吗?另外,您是否自己创建表单?我正在考虑在其创建过程中是否有可能进行黑客攻击,这将对我们以后有所帮助;我自己创建表单。我想我可以跟踪深度并利用它。。。虽然如果可以避免,它会更好。我想到了一个快速而肮脏的黑客,但只有当您使用
list
builtin(无列表理解)生成列表时,它才会起作用。您将创建list的子类,覆盖前面提到的比较方法,然后将该子类临时分配给
list
名称。这样,您就可以快速轻松地创建增强列表,然后恢复列表内置以供进一步使用。听起来怎么样?是的,我现在就是这么做的。似乎是最好的选择,虽然感觉很不对。。。
try:
    [0, 1] < 2
except TypeError:
    # return or assign False. True is not actually meaningful.
try:
    x.sort()
except TypeError:
    pass    # Do nothing. Python would produce meaningless results, anyway.
a = [[[0, 1], [2, 3]], [0, 1]]
b = [[0, 1], [2, 3]]

def deep_annotate(item):
    if isinstance(item, list):
        return (1, [deep_annotate(i) for i in item])
    else:
        return (0, item)

deep_annotate(a) < deep_annotate(b)
#>>> False

deep_annotate(a) > deep_annotate(b)
#>>> True