假设我有两个向量:如何根据haskell中另一个向量的排序顺序重新排序向量值?
let x = V.fromList ["foo", "bar", "baz"]
let y = V.fromList [1,3,2]
我想定义一个矢量y'
这是y
排序的版本,但我也希望这是基于y
排序顺序(有序定义的重新排序x'
x'
应该看起来像["foo", "baz", "bar"]
)。
这样做的最佳功能是什么?理想情况下,我想避免从头开始编写排序功能。
假设我有两个向量:如何根据haskell中另一个向量的排序顺序重新排序向量值?
let x = V.fromList ["foo", "bar", "baz"]
let y = V.fromList [1,3,2]
我想定义一个矢量y'
这是y
排序的版本,但我也希望这是基于y
排序顺序(有序定义的重新排序x'
x'
应该看起来像["foo", "baz", "bar"]
)。
这样做的最佳功能是什么?理想情况下,我想避免从头开始编写排序功能。
下面是一个基于列表的方式:
> import Data.List
> let x = ["foo", "bar", "baz"]
> let y = [1,3,2]
> map snd . sort $ zip y x
["foo","baz","bar"]
基本上,我们拉链所以获得我们对它进行排序对
[(1,"foo"),(3,"bar"),(2,"baz")]
然后列表,字典顺序,从而使第一部分更重要。
最后,我们丢弃第一个组件。
你应该能够适应这个向量。
是否有Data.List(排序)的前往式替代?大多数矢量分类功能似乎是针对可变/盒装变体的。 – daj
我想你正在寻找backpermute
backpermute :: Vector a -> Vector Int -> Vector a
O(n)的产率通过
xs!i
替换索引向量中的每个元素i
获得的矢量。这相当于map (xs!)
是但通常效率更高。
排序向量索引比较索引值;然后permute这两个向量基于排序的索引。 Data.Vector.Algorithms.Intro提供 introsort为可变载体和modify
提供安全破坏性更新使用ST Monad。
import Data.Ord (comparing)
import Data.Vector.Algorithms.Intro (sortBy)
import Data.Vector.Unboxed (generate, modify)
import Data.Vector (Vector, unsafeIndex, backpermute, convert, fromList)
import qualified Data.Vector as V
reorder :: (Ord b) => Vector a -> Vector b -> (Vector a, Vector b)
reorder a b = (backpermute a idx, backpermute b idx)
where
idx = convert $ modify (sortBy comp) init
comp = comparing $ unsafeIndex b -- comparing function
init = generate (V.length b) id -- [0..size - 1]
然后,
\> reorder (fromList ["foo", "bar", "baz"]) $ fromList [1, 3, 2]
(["foo","baz","bar"],[1,2,3])
'V.fromList $ sortOn SND(V.toList(V.zip XY))' – pdexter
@pdexter,不会使用来自'矢量algorithms'排序与'Data.Vector.Modify'一起比转换为列表,排序和转换回来还快? – dfeuer
@dfeuer,是的,最有可能的 – pdexter