如何返回一个sorting列表的索引?

我需要对列表进行sorting,然后返回列表中带有sorting项目索引的列表。 例如,如果我想sorting的列表是[2,3,1,4,5] ,我需要返回[2,0,1,3,4]

这个问题是张贴在字节上,但我想我会在这里重新发布。 http://bytes.com/topic/python/answers/44513-sorting-list-then-return-index-sorted-item

我的具体需要根据对象的属性对对象列表进行sorting。 然后我需要重新排列相应的列表来匹配新sorting列表的顺序。

有没有一个好的方法来做到这一点?

您可以使用pythonsorting函数的key参数来对索引数组进行sorting。

 >>> s = [2, 3, 1, 4, 5] >>> sorted(range(len(s)), key=lambda k: s[k]) [2, 0, 1, 3, 4] >>> 

你可以用numpy的argsort方法做到这一点,如果你有numpy:

 >>> 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]) 

如果没有,从这个问题来看,这是最快的方法:

 >>> vals = [2,3,1,4,5] >>> sorted(range(len(vals)), key=vals.__getitem__) [2, 0, 1, 3, 4] 

怎么样

 l1 = [2,3,1,4,5] l2 = [l1.index(x) for x in sorted(l1)] 

如果你需要sorting列表和指数列表,你可以这样做:

 >>> 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(没有itemgettersorted ):

 >>> temp = [(v,i) for i,v in enumerate(L)] >>> temp.sort >>> indices, L_sorted = zip(*temp) 

ps zip(*iterable)成语反转压缩过程(unzip)。


更新:

为了处理你的具体要求:

“我特别需要根据对象的属性对对象列表进行sorting,然后我需要重新排列相应的列表以匹配新sorting的列表的顺序。

这是一个冗长的做法。 您可以通过将两个列表压缩在一起,然后使用对象属性作为sorting键(以及之后的解压缩)进行sorting来实现这一目的。

 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)) 

这是一个简单的例子,用string来表示你的对象。 这里我们使用string的长度作为分类的关键。

 >>> 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] 

你可以使用numpy.argsort

或者你可以这样做:

 test = [2,3,1,4,5] idxs = zip(*sorted([(val, i) for i, val in enumerate(test)]))[1] 

我会做什么,看你的具体需求:

假设列表a有一些值,而您的键在列表b存储的对象的属性x

 keys = {i:jx for i,j in zip(a, b)} a.sort(key=keys.__get_item__) 

使用这种方法,您可以定制您的列表,而无需构build您所要求的中间置换列表。

直接从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