我有一个数字列表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]
答案 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)
首先,用a
和range(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]