gpt4 book ai didi

python - 如何对不同类型的列表进行排序?

转载 作者:行者123 更新时间:2023-11-28 21:11:46 26 4
gpt4 key购买 nike

我需要使用 python 3 对列表进行排序。可能有 stringsintegersfloatstuples

我目前正在尝试使用 key 参数正确使用 sort 函数,如下所示:

data.sort(key=gen_key)

...

def gen_key(self, value):
if is_number(value):
return str(value)

if isinstance(value, str):
return value
return '___' + type(value).__name__

但问题是现在数字将自然排序。虽然我想对数字和 float 进行排序,但仍然像数字和 float 一样排序,而不是将它们视为字符串。

该行为是由 return str(value) 部分引起的。但是我不能返回与字符串不同的类型,因为这会引发异常,从 python 3 开始,字符串不会像在 python 2 中那样按数字排序。异常如下

unordarable types: int() < str()

有什么建议吗?

最佳答案

诀窍是让您的 key 函数在第一个索引中返回一个具有保证可比较类型的元组,并在后续索引中返回不同类型。

虽然与 Python 2 所做的并非 100% 相同,但对于“前面的数字,其他所有内容按类型名进行比较”的特定情况,您可以使用相当高效的 key 函数来完成此操作:

>>> from numbers import Number
>>> seq = ['Z', 3, 'Y', 1, 'X', 2.5, False, (1, 2), [2, 3], None]
>>> sorted(seq, key=lambda x: (x is not None, '' if isinstance(x, Number) else type(x).__name__, x))
[None, False, 1, 2.5, 3, [2, 3], 'X', 'Y', 'Z', (1, 2)]

这里的key函数将key的第一个元素变成了一个简单的bool,强制None进行排序在其他一切之前(Py2 做了同样的事情),然后首先通过使用空字符串作为键的第二部分对所有数字类型进行排序,其中其他一切都使用它们的类型名称(也像 Py2)。一旦您通过了前两个索引,剩下的就是相同的类型,应该可以很好地进行比较。

这里的主要缺陷是可比较的非数字类型,如 setfrozenset 不会相互比较,它们只会按类型名排序(a使用异常的自定义键类可以处理这个问题)。

它也不会处理递归情况;如果序列包含 [2, 3]['a', 'b'],它将有一个 TypeError 比较 2'a',但只有一个可笑的关键类才能解决这个问题。

如果这不是问题,则运行成本低且相对简单。

与涉及定义为执行比较的 __lt__ 的自定义类的解决方案不同,这种方法具有生成内置键的优势,在排序过程中可以通过最少的 Python 级代码执行进行高效比较。

时间:

 # Multiply out the sequence so log n factor in n log n work counts for something
>>> seq = ['Z', 3, 'Y', 1, 'X', 2.5, False, (1, 2), [2, 3], None] * 100

# Verify equivalence
>>> sorted(seq, key=Py2Key) == sorted(seq, key=lambda x: (x is not None, '' if isinstance(x, Number) else type(x).__name__, x))
True

# Timings in seconds for the fastest time (of 3 trials) to run the sort 1000 times:
>>> import timeit

# Py2Key class
>>> min(timeit.repeat('sorted(seq, key=Py2Key)', 'from __main__ import seq, Py2Key', number=1000))
5.251885865057375

>>> min(timeit.repeat('sorted(seq, key=lambda x: (x is not None, "" if isinstance(x, Number) else type(x).__name__, x))', 'from __main__ import seq, Number', number=1000))
1.9556877178131344

基本上,避免动态 Python 级 __lt__ 的开销将运行时间减少了 60% 以上。这似乎不是算法改进(seq 长 100 倍具有相同的运行时间比率),只是固定开销的减少,但这是一个重要的减少。

关于python - 如何对不同类型的列表进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34756863/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com