通过重新排序元组排序元组列表

Vin*_*eet 5 python sorting performance tuples

给定要排序的元组列表,python将根据元组中的第一个元素,然后是第二个元素等对它们进行排序.

>>> A
[(3, 2, 1), (0, 3, 0), (2, 1, 0), (2, 2, 3), (0, 3, 2), (2, 1, 1), (3, 3, 2), (3, 2, 0)]
>>> sorted(A)
[(0, 3, 0), (0, 3, 2), (2, 1, 0), (2, 1, 1), (2, 2, 3), (3, 2, 0), (3, 2, 1), (3, 3, 2)]
Run Code Online (Sandbox Code Playgroud)

这非常有效.现在我想用第三个元素排序它们,然后是第一个元素,然后是第二个元素,我可以通过提供一个键函数或一个cmp函数来完成它.

>>> A
[(3, 2, 1), (0, 3, 0), (2, 1, 0), (2, 2, 3), (0, 3, 2), (2, 1, 1), (3, 3, 2), (3, 2, 0)]
>>> sorted(A, key = lambda x: (x[2], x[0], x[1]))
[(0, 3, 0), (2, 1, 0), (3, 2, 0), (2, 1, 1), (3, 2, 1), (0, 3, 2), (3, 3, 2), (2, 2, 3)]
Run Code Online (Sandbox Code Playgroud)

除了我的主要性能惩罚

s ="""\
from numpy.random import randint as rr
A=[tuple(rr(0,10,3)) for i in range(100)]
def tuplecmp(t1, t2):
    return t1[0] - t2[0]
"""
c1 = """\
sorted(A)
"""
c2 = """\
sorted(A, key=lambda x: (x[2], x[0], x[1]))
"""
c3 = """\
sorted(A, cmp = tuplecmp)
"""
import timeit
print timeit.timeit(c1,number=10000, setup= s)
print timeit.timeit(c2,number=10000, setup= s)
print timeit.timeit(c3,number=10000, setup= s)
Run Code Online (Sandbox Code Playgroud)

0.60133600235,
0.980231046677,
2.68837809563
Run Code Online (Sandbox Code Playgroud)

此外,我比较各个元组元素的顺序不需要保持相同.我可能需要比较"第二个,第一个,然后第三个"元素等.有没有更好的方法来提供任意比较器功能而不会造成重大的性能损失;

kin*_*all 5

使用operator.itemgetter你的key功能可能会更快; 你必须尝试一下.

import operator
sorted(A, key=operator.itemgetter(2, 0, 1))
Run Code Online (Sandbox Code Playgroud)