是否有與NumPy的argsort
函數等價的標準Haskell?高效的Haskell相當於NumPy的參數
我使用的是HMatrix,所以想要一個兼容Vector R
的函數,它是Data.Vector.Storable.Vector Double
的別名。下面的argSort
功能是我目前使用的實現:
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import qualified Data.List as L
import qualified Data.Vector as V
import qualified Data.Vector.Storable as VS
import Prelude (($), Double, IO, Int, compare, print, snd)
a :: VS.Vector Double
a = VS.fromList [40.0, 20.0, 10.0, 11.0]
argSort :: VS.Vector Double -> V.Vector Int
argSort xs = V.fromList (L.map snd $ L.sortBy (\(x0, _) (x1, _) -> compare x0 x1) (L.zip (VS.toList xs) [0..]))
main :: IO()
main = print $ argSort a -- yields [2,3,1,0]
我使用明確的合格import
的只有我要說清楚,每一個類型和功能的來源。
該實現不是非常有效,因爲它將輸入向量轉換爲列表並將結果轉換回向量。有沒有像這樣(但更高效)的地方存在?
更新
@leftaroundabout有一個很好的解決方案。這是我結束了的溶液:
module LAUtil.Sorting
(IndexVector
, argSort
)
where
import Control.Monad
import Control.Monad.ST
import Data.Ord
import qualified Data.Vector.Algorithms.Intro as VAI
import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Numeric.LinearAlgebra
type IndexVector = VU.Vector Int
argSort :: Vector R -> IndexVector
argSort xs = runST $ do
let l = VS.length xs
t0 <- VUM.new l
forM_ [0..l - 1] $
\i -> VUM.unsafeWrite t0 i (i, (VS.!) xs i)
VAI.sortBy (comparing snd) t0
t1 <- VUM.new l
forM_ [0..l - 1] $
\i -> VUM.unsafeRead t0 i >>= \(x, _) -> VUM.unsafeWrite t1 i x
VU.freeze t1
這是更直接地與可用Numeric.LinearAlgebra
由於數據載體是Storable
。這爲索引使用了unboxed向量。