我需要对列表进行排序,然后返回一个列表,其中包含列表中已排序项的索引。例如,如果我要排序的列表是[2,3,1,4,5]
,我需要返回[2,0,1,3,4]
。
这个问题是在字节上发布的,但我想我会在这里重新发布。 http://bytes.com/topic/python/answers/44513-sorting-list-then-return-index-sorted-item
我特别需要根据对象的属性对对象列表进行排序。然后,我需要重新排序相应的列表以匹配新排序列表的顺序。
有没有好办法呢?
答案 0 :(得分:178)
您可以使用python排序函数'key
参数来代替索引数组。
>>> s = [2, 3, 1, 4, 5]
>>> sorted(range(len(s)), key=lambda k: s[k])
[2, 0, 1, 3, 4]
>>>
答案 1 :(得分:64)
如果您有可用的numpy,可以使用numpy的argsort方法执行此操作:
>>> import numpy
>>> vals = numpy.array([2,3,1,4,5])
>>> vals
array([2, 3, 1, 4, 5])
>>> sort_index = numpy.argsort(vals)
>>> sort_index
array([2, 0, 1, 3, 4])
如果不可用,取自this question,这是最快的方法:
>>> vals = [2,3,1,4,5]
>>> sorted(range(len(vals)), key=vals.__getitem__)
[2, 0, 1, 3, 4]
答案 2 :(得分:11)
如果你需要排序列表和索引列表,你可以这样做:
>>> L = [2,3,1,4,5]
>>> from operator import itemgetter
>>> indices, L_sorted = zip(*sorted(enumerate(L), key=itemgetter(1)))
>>> list(L_sorted)
[1, 2, 3, 4, 5]
>>> list(indices)
[2, 0, 1, 3, 4]
或者,对于Python< 2.4(无itemgetter
或sorted
):
>>> temp = [(v,i) for i,v in enumerate(L)]
>>> temp.sort
>>> indices, L_sorted = zip(*temp)
P.S。 zip(*iterable)
成语反转了zip进程(解压缩)。
处理您的具体要求:
“我特别需要根据对象的属性对对象列表进行排序。然后我需要重新排序相应的列表以匹配新排序列表的顺序。”
这是一种冗长的做法。您可以通过将两个列表压缩在一起来实现单一排序,然后使用object属性作为排序键进行排序(并在之后解压缩)。
zipped = zip(obj_list, secondary_list)
zipped_sorted = sorted(combined, key=lambda x: x[0].some_obj_attribute)
obj_list, secondary_list = map(list, zip(*zipped_sorted))
这是一个简单的例子,使用字符串来表示你的对象。这里我们使用字符串的长度作为排序的关键。:
>>> str_list = ["banana", "apple", "nom", "Eeeeeeeeeeek"]
>>> sec_list = [0.123423, 9.231, 23, 10.11001]
>>> temp = sorted(zip(str_list, sec_list), key=lambda x: len(x[0]))
>>> str_list, sec_list = map(list, zip(*temp))
>>> str_list
['nom', 'apple', 'banana', 'Eeeeeeeeeeek']
>>> sec_list
[23, 9.231, 0.123423, 10.11001]
答案 3 :(得分:7)
怎么样
l1 = [2,3,1,4,5]
l2 = [l1.index(x) for x in sorted(l1)]
答案 4 :(得分:0)
我会做什么,看看你的具体需求:
假设您的列表a
包含一些值,并且您的密钥位于列表x
中存储的对象的属性b
中
keys = {i:j.x for i,j in zip(a, b)}
a.sort(key=keys.__get_item__)
使用此方法,您可以获得订单,而无需构建您要求的中间排列列表。
答案 5 :(得分:0)
您可以使用numpy.argsort
或者你可以这样做:
test = [2,3,1,4,5]
idxs = zip(*sorted([(val, i) for i, val in enumerate(test)]))[1]
答案 6 :(得分:-2)
直接退出collections.OrderedDict
的文档:
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
改编自原帖中的示例:
>>> l=[2,3,1,4,5]
>>> OrderedDict(sorted(enumerate(l), key=lambda x: x[1])).keys()
[2, 0, 1, 3, 4]
有关详细信息,请参阅http://docs.python.org/library/collections.html#collections.OrderedDict。