列表中元素的相对顺序

时间:2013-07-20 23:21:09

标签: python list relative

我正在编写一个函数,它接受一个整数列表并返回一个相对定位元素的列表。

也就是说,如果我对所述函数的输入是 [1,5,4] ,那么输出将是 [0,2,1] ,因为1是最低元素,5是最高元素,4是中间元素,所有元素都是唯一值,或 set()

但代码说话,我到目前为止的功能是

def relative_order(a):
    rel=[]
    for i in a:
        loc = 0
        for v in a:
            if i > v:
                loc += 1
        rel.append(loc)
    return rel

它确实有效,但由于我将大型列表发送到此函数中,并且我必须将每个元素与每次迭代中的所有元素进行比较,因此需要大约5秒,其中包含10.000个元素的列表。

我的问题是如何提高所述功能的速度,也许更多Pythonic,我尝试了理解列表,但我的Python技能缺乏,我只想出了实现这个问题的必要方法。

5 个答案:

答案 0 :(得分:11)

这可以写成这样的列表理解:

lst = [1, 5, 4]
s = sorted(lst)    
[s.index(x) for x in lst]
=> [0, 2, 1]

这是另一个测试,使用@ frb的例子:

lst = [10, 2, 3, 9]
s = sorted(lst)    
[s.index(x) for x in lst]
=> [3, 0, 1, 2]

答案 1 :(得分:11)

这是另一个应该更有效的保持.index进入列表,因为它表明不会发生重复值,所以我们可以进行查找O(1)而不是线性...(并实际符合要求):

>>> a = [10, 2, 3, 9]
>>> indexed = {v: i for i, v in enumerate(sorted(a))}
>>> map(indexed.get, a)
[3, 0, 1, 2]

答案 2 :(得分:1)

你所拥有的方法需要n ^ 2次才能获得n ^ 2次的命令

这应该在log(n)时间内起作用:

def relative_order(a):
    positions = sorted(range(len(a)), key=lambda i: a[i])
    return sorted(range(len(a)), key = lambda i: positions[i])

它仍然是订单日志(n),因此也适用于您的大型列表。

编辑:

在lambda之外。

答案 3 :(得分:1)

def relative_order(a):
    l = sorted(a)
    # hash table of element -> index in ordered list
    d = dict(zip(l, range(len(l))))
    return [d[e] for e in a]

print relative_order([1, 5, 4])
print relative_order([2, 3, 1])
print relative_order([10, 2, 3, 9])

[0, 2, 1]
[1, 2, 0]
[3, 0, 1, 2]

该算法应该与sort类似,但使用额外的空间。

答案 4 :(得分:-1)

您的问题是关于排序。我建议使用Numpy或'Numeric Python'。 Numpy是一个Python模块,针对“快速,紧凑,多维数组设备”进行了优化。它是Python中科学计算的首选软件包。 http://www.numpy.org/

import numpy as np

input_array = np.array([1, 5, 4])
sorted_indices = np.argsort(input_array)

print sorted_indices
#[0 2, 1]

我还根据大小为50000的数组添加了探查器输出。它表明这个方法比使用Python sorted函数快了大约4倍(按照前面的答案)。

ncalls  tottime  percall  cumtime  percall filename:lineno(function)

    1    0.009    0.009    0.009    0.009 {method 'argsort' of 'numpy.ndarray' objects}
    1    0.034    0.034    0.034    0.034 {sorted}

警告: 评论建议答案不符合作者的功能。这是真的。我想argsort的全部意义在于:

sorted_array = input_array[sorted_indices] 

为您提供排序数组。

OP很奇怪,我想要一个结果,需要通过以下方式提供排序数组:

for i, val in enumerate(sorted_indices):
    sorted_array[val] = input_array[i]