【发布时间】:2012-05-28 12:53:37
【问题描述】:
我有一个看起来像这样的元组列表:
[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
我想按元组内的整数值升序对该列表进行排序。有可能吗?
【问题讨论】:
我有一个看起来像这样的元组列表:
[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
我想按元组内的整数值升序对该列表进行排序。有可能吗?
【问题讨论】:
>>> 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
【讨论】:
itemgetter() 是一个更好的解决方案。但是,我认为 lambda 表达式会让 key 的功能更加清晰。
time `python -c "the code"` 然后我得到了你拼出的“人眼”结果,以及更快的系统时钟时间。仍然不确定为什么会这样,但它是可重现的。我认为这与加载模块的开销有关,但对我来说仍然不是很重要。
python -m timeit -s 内部进行导入,但是是的,我认为您说得对,在生产场景中您只需支付一次 lib 负载惩罚。而且...至于谁在乎那微秒...您在乎是因为假设您的排序数据会变得非常大,并且一旦数据集增长,该微秒就会变成真正的秒数。
尝试将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(some_list, lambda x: (x[0], -x[1],))
来自 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)]
【讨论】:
作为一个 python 新手,我只想提一下,如果数据确实看起来像这样:
data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
然后sorted() 将自动按元组中的第二个元素排序,因为第一个元素都是相同的。
【讨论】:
添加到 Cheeken 的回答中, 这就是您按降序的第二项对元组列表进行排序的方式。
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)],key=lambda x: x[1], reverse=True)
【讨论】:
sorted 函数只生成一个为您排序的新列表。
对于避免 lambda 的方法,首先定义自己的函数:
def MyFn(a):
return a[1]
然后:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=MyFn)
【讨论】:
lambda x: x[1] 放在多个代码区域中。
对于Python 2.7+,这可以使接受的答案更具可读性:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda (k, val): val)
【讨论】:
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')]
【讨论】:
对于就地排序,请使用
foo = [(list of tuples)]
foo.sort(key=lambda x:x[0]) #To sort by first element of the tuple
【讨论】: