获取数值列表中元素层次结构的Python方法

时间:2019-08-09 17:32:46

标签: python

我有一个数字列表a,我想输出一个列表,其中每个元素的层次结构位置都为a(最高值为0,第二高为1,依此类推)。

我想知道这是否是使用Python的最有效的方法。也许有更好的方法?

a = [3,5,6,25,-3,100]
b = sorted(a)
b = b[::-1]
[b.index(i) for i in a]

4 个答案:

答案 0 :(得分:1)

您也可以numpy.argsort(-a)-a,因为argsort假定升序)。对于大型阵列,它可能具有更好的性能(尽管据我所知没有官方分析)。

答案 1 :(得分:1)

解决方案的一个问题是重复使用index,这将使您最终的理解为O(n ** 2),因为index每次都必须经过排序的列表。 / p>

使用已排序列表中每个值的排名构建dict会更有效:

a = [3,5,6,25,-3,100]

ranks = {val:idx for idx, val in enumerate(sorted(a, reverse=True))}
# {100: 0, 25: 1, 6: 2, 5: 3, 3: 4, -3: 5}
out = [ranks[val] for val in a]

print(out)
# [4, 3, 2, 1, 5, 0]

为了在O(n)中拥有最后一步。

答案 2 :(得分:1)

@ThierryLathuille的答案仅在输入列表中没有重复项时有效,因为答案依赖于以列表值作为键的字典。如果列表中可能有重复项,则应使用enumerate生成的索引对输入列表中的项目进行排序,然后将这些索引映射到其排序位置:

from operator import itemgetter
mapping = dict(zip(map(itemgetter(0), sorted(enumerate(a), key=itemgetter(1), reverse=True)), range(len(a))))

mapping变为:

{5: 0, 3: 1, 2: 2, 1: 3, 0: 4, 4: 5}

,以便随后可以遍历列表的长度索引以按顺序获得排序位置:

[mapping[i] for i in range(len(a))]

返回:

[4, 3, 2, 1, 5, 0]

答案 3 :(得分:0)

首先,用arange(len(a)) sort来创建一个元组列表(元素及其位置),zip以相反的顺序{ {1}}用range(len(a))来标记排序后每个元素的位置,现在取消排序此列表(通过基于每个元素的原始位置对其进行排序),并最终在获取每个元素的位置时被排序

>>> a = [3,5,6,25,-3,100]
>>> [i for _,i in sorted(zip(sorted(zip(a, range(len(a))), reverse=True), range(len(a))), key=lambda t:t[0][1])]
[4, 3, 2, 1, 5, 0]