在python中快速排序变量

时间:2015-01-02 20:34:47

标签: python cython ranking

我想知道对变量进行排序的最快方法是什么?我有4个整数变量,我需要快速排名。这个过程需要运行很多次,因此需要快速。我尝试使用一个计数器和counter()。most_common()函数,它运行良好,但比单个变量计数要慢。这是我正在运行的一个例子。

A = 15
B = 10
C = 5
D = 10

def get_highest(A,B,C,D):
    count = A
    label = 'A'
    if B >= count:
        count = B
        label = 'B'
    if C >= count:
        count = C
        label = 'C'
    if D >= count:
        count = D
        label = 'D'

    return count, label

highest, label = get_highest(A,B,C,D)
if label == 'A':
    A=0
if label == 'B':
    B=0
if label == 'C':
    C=0
if label == 'D':
    D=0
second_highest, label = get_highest(A,B,C,D)

我一直持续到获得所有变量的排名。我想知道是否有更快的方法来做到这一点?我也想在cython中实现这一点,所以在cython中实现时可以加速的答案将不胜感激。

3 个答案:

答案 0 :(得分:2)

这是您的功能的更快替代方案:

import operator

def get_highest(A,B,C,D):
    return max(zip((A, B, C, D), 'ABCD'), key=operator.itemgetter(0))

但是,如果你的目标是将最大值变量归零,那么你可能最好让这个函数做得更多:

def max_becomes_zero(A, B, C, D):
    temp = [A, B, C, D]
    maxind, maxval = max(enumerate(temp), key=operator.itemgetter(1))
    maxname = 'ABCD'[maxind]
    temp[maxind] = 0
    return temp, maxval, maxname

如下调用:

(A, B, C, D), highest, label = max_becomes_zero(A, B, C, D)

补充:有些人可能会怀疑(并且在评论中询问)operator.itemgetter与lambda的相对速度。答:不要怀疑,衡量。这就是Python标准库中的timeit模块 ...:

$ python -mtimeit -s'a="something"' 'max(enumerate(a), key=lambda x: x[1])'
1000000 loops, best of 3: 1.56 usec per loop
$ python -mtimeit -s'a="something"; import operator' 'max(enumerate(a), operator.itemgetter(1))'
1000000 loops, best of 3: 0.363 usec per loop

如您所见,在这种特殊情况下(在我的Linux工作站上,使用Python 2.7.9),整个操作的加速度令人印象深刻 - 速度提高了4倍以上,每次重复节省超过1微秒。 / p>

更一般地说,在可行的情况下避免lambda会让你更开心。

注意:确定实际操作的时间非常重要 - 只需在启动时初始化aimport,例如{ {1}}表示-s表单中命令行(推荐)使用timeit的标记;我怀疑这个错误显然阻止了评论者重现这些结果(只是猜测,因为评论者向我们展示了确切的代码,当然)。

答案 1 :(得分:1)

以下在我的机器上花费3μs以下来完成整个排名:

In [43]: [name for (val, name) in sorted(zip((A, B, C, D), "ABCD"))][::-1]
Out[43]: ['A', 'D', 'B', 'C']

In [44]: %timeit [name for (val, name) in sorted(zip((A, B, C, D), "ABCD"))][::-1]
100000 loops, best of 3: 2.71 us per loop

或者这个怎​​么样(我希望我的比较正确: - )):

def rank1(A, B, C, D):
  lA, lB, lC, lD = "A", "B", "C", "D"
  if A < B:
    A, B, lA, lB = B, A, lB, lA
  if C < D:
    C, D, lC, lD = D, C, lD, lC
  if A < C:
    A, C, lA, lC = C, A, lC, lA
  if B < D:
    B, D, lB, lD = D, B, lD, lB
  if B < C:
    B, C, lB, lC = C, B, lC, lB
  return (A, B, C, D), (lA, lB, lC, lD)

整个排名为770ns:

In [6]: %timeit rank1(A, B, C, D)
1000000 loops, best of 3: 765 ns per loop

答案 2 :(得分:0)

可能值得尝试sort变量:

ordered = sorted(list(zip("ABCD", (A, B, C, D))), key=lambda x: x[1])

>>> print(ordered)
[('C', 5), ('B', 10), ('D', 10), ('A', 15)]