2012-10-16 91 views
2

我需要排序數組,同時返回一個包含原始元素排序位置的數組。 (NB不是argsort,所述索引來對數組進行排序)排序:返回一個數組,每個元素的新位置

目前這需要兩個步驟:

  1. 一種argsort
  2. 一個新的陣列上的散佈操作 即POS [argsort [I] ] =我

我覺得我錯過了這裏的一招。這是一個衆所周知的算法,我忽略了一步就可以實現的算法嗎?

步驟2也可以通過搜索實現,但我認爲分散效率更高。

我已經包含了一些示例python代碼來說明問題。

import numpy as np 

l = [0,-8,1,10,13,2] 

a = np.argsort(l) 
# returns [1 0 2 5 3 4], the order required to sort l 

# init new list to zero 
pos = [0 for x in range(0,len(l))] 

# scatter http://en.wikipedia.org/wiki/Gather-scatter_(vector_addressing) 
for i in range(0,len(l)): 
     pos[a[i]] = i 

print pos 
# prints [1, 0, 2, 4, 5, 3], i.e. each original indexes new position in the sorted array 

尋找對這個問題的引用讓我感到沮喪,也許我錯過了這種類型的操作正確的術語。

任何幫助或指導將不勝感激。

+0

我之前幾次做,甚至不知道那是微不足道的改造人決定把它收集*散射*。儘管如此,我看不出爲什麼你這麼注視這個 – Alexander

+0

原始元素的排序位置是由argsort給出的。您的代碼打印排序元素的原始位置。 –

+0

另外注意,你可以通過應用兩次'argsort'函數來達到同樣的效果,但顯然這是不理想的 – Alexander

回答

0

下面是一個簡單的實現,儘管它在任何有意義的意義上都不是「就地」的。我不確定「in-place」是什麼意思,因爲輸出是int類型的np.array,輸入可以包含雙精度。

更新響應@夫的評論和澄清意圖:

#!/usr/bin/env python 

import numpy as np 

unsorted = np.array([0,-8,1,10,13,2]) 

def myargsort(numbers): 
    tuples = enumerate(numbers) # returns iterable of index,value 
    sortedTuples = sorted(tuples,key = lambda pair: pair[1]) 
    sortedNumbers = [num for idx,num in sortedTuples] 
    sortIndexes = [idx for idx,num in sortedTuples] 
    return (sortedNumbers,sortIndexes) 

sortedNums, sortIndices = myargsort(unsorted) 

print(unsorted) 
print(sortedNums) 
print(sortIndices) 
+1

它看起來這種方法需要兩次排序操作。原始方法看起來更高效,因爲它需要一次排序操作並列出遍歷一次。 – norio

+1

@norio,不確定3年前我在想什麼,但回過頭來看原來的問題,我懷疑我的版本實際上完成了他想要的,這可能就是你的觀點。儘管只有一種排序方式,但還是有一個收集操作來將結果應用於數字列表。 – philwalk

+0

作爲算法的一部分,我以前在以前的版本中將'np.argsort'錯誤地寫入了'print(..)'中。這就是爲什麼我寫了「分類操作兩次」。對不起。我在上面撤回了我的評論。 (你對前一個函數的輸出與OP想要的區別是對的,但是我太粗心了,注意到它。) – norio

相關問題