正确的解决方案是使用key
返回元组的函数,如 unutbu 的答案所示。但是,还有另一种方法。Python的排序保证是稳定的,所以你可以通过不同的key进行多次排序,达到你想要的输出。尤其:
list_.sort(key=lambda x: float(x[1]))
list_.sort(key=lambda x: len(x[1]))
list_.sort(key=lambda x: x[0])
使用 IPython 演示:
In [1]: list_ = [(1, '0101'), (1, '1010'), (1, '101'), (2, '01'), (2, '010'), (2, '10')]
In [2]: list_.sort(key=lambda x: float(x[1]))
...: list_.sort(key=lambda x: len(x[1]))
...: list_.sort(key=lambda x: x[0])
...:
In [3]: list_
Out[3]: [(1, '101'), (1, '0101'), (1, '1010'), (2, '01'), (2, '10'), (2, '010')]
注意:此解决方案类似于您在问题中描述的三个步骤,但步骤相反!最后按主键排序以获得正确的输出。
还要记住,用于排序的算法是自适应的。这意味着当一个序列已经部分排序时,它可以使用部分顺序来更有效地排序(通常在线性时间而不是nlog(n)
)。当您按多个键排序时,您通常会实现这种偏序,因此多次调用sort()
不会花费太多。然而,它高度依赖于密钥和数据。有时它比使用元组作为键更有效,有时它很慢。
时间的一个例子。请注意,这两种解决方案大多需要相同的时间。
In [9]: list_
Out[9]: [(1, '0101'), (1, '1010'), (1, '101'), (2, '01'), (2, '010'), (2, '10')]
In [10]: list_ *= 1000 # better to avoid too small benchmarks.
In [11]: %%timeit
...: a = sorted(list_, key=lambda x: (x[0], len(x[1]), float(x[1])))
...:
100 loops, best of 3: 6.04 ms per loop
In [12]: %%timeit
...: a = sorted(list_, key=lambda x: float(x[1]))
...: a.sort(key=lambda x: len(x[1]))
...: a.sort(key=lambda x: x[0])
...:
100 loops, best of 3: 5.72 ms per loop
In [13]: import random
...: data = [(random.randint(1, 1000), bin(random.randint(1, 100))[2:]) for _ in range(10000)]
...:
In [14]: %%timeit
...: a = sorted(data, key=lambda x: (x[0], len(x[1]), float(x[1])))
...:
100 loops, best of 3: 15.2 ms per loop
In [15]: %%timeit
...: a = sorted(data, key=lambda x: float(x[1]))
...: a.sort(key=lambda x: len(x[1]))
...: a.sort(key=lambda x: x[0])
...:
100 loops, best of 3: 15.1 ms per loop