按第二项(整数值)对元组列表进行排序[重复]
Posted
技术标签:
【中文标题】按第二项(整数值)对元组列表进行排序[重复]【英文标题】:Sort a list of tuples by 2nd item (integer value) [duplicate] 【发布时间】:2012-05-28 12:53:37 【问题描述】:我有一个看起来像这样的元组列表:
[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
我想按元组内的整数值升序对该列表进行排序。有可能吗?
【问题讨论】:
【参考方案1】:>>> from operator import itemgetter
>>> data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
>>> sorted(data,key=itemgetter(1))
[('abc', 121), ('abc', 148), ('abc', 221), ('abc', 231)]
在这种情况下,使用 itemgetter
的 IMO 比 @cheeken 的解决方案更具可读性。它是
也更快,因为几乎所有的计算都将在c
端(没有双关语)而不是通过使用lambda
完成。
>python -m timeit -s "from operator import itemgetter; data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=itemgetter(1))"
1000000 loops, best of 3: 1.22 usec per loop
>python -m timeit -s "data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=lambda x: x[1])"
1000000 loops, best of 3: 1.4 usec per loop
【讨论】:
+1 我同意itemgetter()
是一个更好的解决方案。但是,我认为 lambda 表达式会让 key
的功能更加清晰。
+1 但是,当我对您的速度进行测试时,我注意到“人眼”应该更快......并且测量得更快,实际上明显慢了。我对此挠了挠头,然后停止使用 python 超时模块,只使用 linux 时间。即time `python -c "the code"`
然后我得到了你拼出的“人眼”结果,以及更快的系统时钟时间。仍然不确定为什么会这样,但它是可重现的。我认为这与加载模块的开销有关,但对我来说仍然不是很重要。
@JeffSheffield:注意 jamylak 是在设置代码中进行导入(在计时之外),而不是测试代码。这是完全合理的,因为大多数程序需要不止一次排序,或者需要对更大的集合进行排序,但它们只会导入一次。 (对于那些只需要做一个小排序的程序......好吧,你说的是不到一微秒的差异,那么谁在乎呢?)
@abarnert 仅供参考:jamlak 正在 python -m timeit -s
内部进行导入,但是是的,我认为您说得对,在生产场景中您只需支付一次 lib 负载惩罚。而且...至于谁在乎那微秒...您在乎是因为假设您的排序数据会变得非常大,并且一旦数据集增长,该微秒就会变成真正的秒数。
@JeffSheffield:这正是重点:导入的成本不会随着数据的增长而增加,所以即使它看起来像是 1us 的很大一部分,你正在为一种小类支付,它是将成为您为一大类或一堆小类支付的 500 毫秒的不相关部分。【参考方案2】:
尝试将key
关键字与sorted()
结合使用。
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda x: x[1])
key
应该是一个函数,用于标识如何从数据结构中检索可比较元素。在您的情况下,它是元组的第二个元素,因此我们访问 [1]
。
有关优化,请参阅 jamylak 使用 itemgetter(1)
的回复,它本质上是 lambda x: x[1]
的更快版本。
【讨论】:
虽然很明显。排序后没有排序,所以: sorted_list = sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda x : x[1]) ,reverse=True 表示从大到小。 这仍然适用于 Python 3.7。 您也可以将多个键添加为一个元组,如果您想要一个反转您可以添加一个负号,这将使用第一个元素然后第二个元素进行排序:sorted(some_list, lambda x: (x[0], -x[1],))
我只想说这是我有史以来访问量最大的 *** 页面;到目前为止,我已经轻松地来过这里 500 次。谢谢厚脸皮,要是我能记住这一行代码就好了。【参考方案3】:
来自 python 维基:
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
【讨论】:
x = [[[5,3],1.0345],[[5,6],5.098],[[5,4],4.89],[[5,1],5.97] ] 对于这样的列表,我们可以使用 itemgetter() 对 x[0][1] 中的元素进行排序吗?【参考方案4】:作为一个 python 新手,我只想提一下,如果数据确实看起来像这样:
data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
然后sorted()
将自动按元组中的第二个元素排序,因为第一个元素都是相同的。
【讨论】:
【参考方案5】:添加到 Cheeken 的回答中, 这就是您按降序的第二项对元组列表进行排序的方式。
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)],key=lambda x: x[1], reverse=True)
【讨论】:
请注意,不会更改原始列表。sorted
函数只生成一个为您排序的新列表。【参考方案6】:
对于避免 lambda 的方法,首先定义自己的函数:
def MyFn(a):
return a[1]
然后:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=MyFn)
【讨论】:
这样做有什么好处? 一个好处是拥有一个可以在任何地方使用的已定义函数,而无需将lambda x: x[1]
放在多个代码区域中。
另一个好处是,如果它是一个单独的函数,您可以更好地记录/评论。【参考方案7】:
对于Python 2.7+
,这可以使接受的答案更具可读性:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda (k, val): val)
【讨论】:
【参考方案8】:OP 中的排序值是整数这一事实与问题本身无关。换句话说,如果排序值为文本,则接受的答案将起作用。我提出这一点还指出可以在排序期间修改排序(例如,考虑大小写)。
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: x[1])
[(148, 'ABC'), (221, 'DEF'), (121, 'abc'), (231, 'def')]
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: str.lower(x[1]))
[(121, 'abc'), (148, 'ABC'), (231, 'def'), (221, 'DEF')]
【讨论】:
【参考方案9】:对于就地排序,请使用
foo = [(list of tuples)]
foo.sort(key=lambda x:x[0]) #To sort by first element of the tuple
【讨论】:
虽然这个答案可能是正确的,但最好解释一下为什么这个答案是正确的,而不是只提供代码。此外,这几乎是一个已经存在并在 5 年前被接受的答案的确切答案,因此这并没有真正为网站添加任何内容。看看新的问题来帮助人们! 实际上这有助于人们寻找就地排序 虽然这很有帮助,但它可能更适合作为对建议答案的评论,表明人们将如何使用与该答案中提供的方法相同的方法来就地完成相同的任务。以上是关于按第二项(整数值)对元组列表进行排序[重复]的主要内容,如果未能解决你的问题,请参考以下文章