argsort
NumPy の機能に相当する標準的な Haskell はありますか?
私はHMatrixVector 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
すべての型と関数がどこから来ているのかを明確にするために、明示的に修飾された s を使用しています。
この実装は、入力ベクトルをリストに変換し、結果をベクトルに戻すため、あまり効率的ではありません。このような(しかしより効率的な)ものはどこかに存在しますか?
アップデート
@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
. これは、インデックスにボックス化されていないベクトルを使用します。