是否有与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向量。