2016-06-07 84 views
2

假设我有两个向量:如何根据haskell中另一个向量的排序顺序重新排序向量值?

let x = V.fromList ["foo", "bar", "baz"] 
    let y = V.fromList [1,3,2] 

我想定义一个矢量y'这是y排序的版本,但我也希望这是基于y排序顺序(有序定义的重新排序x'x'应该看起来像["foo", "baz", "bar"])。

这样做的最佳功能是什么?理想情况下,我想避免从头开始编写排序功能。

+0

'V.fromList $ sortOn SND(V.toList(V.zip XY))' – pdexter

+1

@pdexter,不会使用来自'矢量algorithms'排序与'Data.Vector.Modify'一起比转换为列表,排序和转换回来还快? – dfeuer

+0

@dfeuer,是的,最有可能的 – pdexter

回答

3

下面是一个基于列表的方式:

> 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")] 

然后列表,字典顺序,从而使第一部分更重要。

最后,我们丢弃第一个组件。

你应该能够适应这个向量。

+0

是否有Data.List(排序)的前往式替代?大多数矢量分类功能似乎是针对可变/盒装变体的。 – daj

5

我想你正在寻找backpermute

backpermute :: Vector a -> Vector Int -> Vector a 

O(n)的产率通过xs!i替换索引向量中的每个元素i获得的矢量。这相当于map (xs!)是但通常效率更高。

1

排序向量索引比较索引值;然后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])