我目前正在尝试对以下列表进行排序:
list_ = [(1, '0101'), (1, '1010'), (1, '101'), (2, '01'), (2, '010'), (2, '10')]
这些是我想要对其进行排序的步骤:
我的尝试:
sorted_by_length = sorted(list_, key=len x:x[1])
但是,我在x
之后收到了有关key= len
的语法错误。
在这种情况下我应该使用的正确变量是什么?
正确的排序列表应为:
sorted_by_length = [(1, '101'), (1, '0101'), (1, '1010'), (2, '01'), (2, '10'), (2, '010')]
感谢您的帮助。
答案 0 :(得分:15)
键功能可以返回元组。
sorted_by_length = sorted(list_,
key=lambda x: (x[0], len(x[1]), float(x[1])))
这是因为元组按字典顺序排序:(元组的第一个元素首先用于排序,然后第二个元素用于打破关系,然后第三个元素用于打破任何剩余的关系。)
有关此问题的解释以及与排序相关的其他问题,请参阅优秀HOWTO Sort。
In [1]: list_ = [(1, '0101'), (1, '1010'), (1, '101'), (2, '01'), (2, '010'), (2, '10')]
In [2]: sorted_by_length = sorted(list_,
key=lambda x: (x[0], len(x[1]), float(x[1])))
...:
In [3]: sorted_by_length
Out[3]: [(1, '101'), (1, '0101'), (1, '1010'), (2, '01'), (2, '10'), (2, '010')]
如果每个元组的第二个元素是二进制文件中int
的字符串表示形式,则在排序键中使用int(x, 2)
而不是float(x)
。如果它们是整数的十进制表示,则使用int(x)
。
答案 1 :(得分:4)
您可以使用返回集合的键函数进行排序
list_.sort(key=lambda x: [x[0], len(x[1]), x[1]])
key
参数,用于指定在进行比较之前在每个列表元素上调用的函数。
如果你使用集合作为key
结果,那么它将使用第一个比较第一个元素进行排序,如果它们相等,那么将比较秒数等等......
P.S。据我所知,没有必要将第三项转换为数字类型,因为如果等于相同,那么对于二进制值,词典和数字排序将给出相同的结果
答案 2 :(得分:2)
正确的解决方案是使用返回元组的key
函数,如unutbu的答案所示。然而,还有另一种方法。 Python的排序保证稳定,因此您可以通过不同的键进行多种排序并实现所需的输出。
特别是:
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')]
注意:此解决方案类似于您在问题中描述的三个步骤,但步骤相反!按主键 last 排序以获得正确的输出。
另请注意,用于排序的算法是自适应的。这意味着当一个序列已经被部分排序时,它可以使用偏序来更有效地排序(通常是线性时间而不是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