Haskell使用索引创建带子向量的向量

时间:2016-05-06 22:11:36

标签: haskell vector haskell-vector

我正在尝试创建一个带有子向量的向量,该子向量包含使用子向量索引向量从另一个向量中取出的元素。 b中的每个元素都对应于a中元素放入c时应具有的子向量索引。

import Data.Vector
let a = fromList [9,2,3,7,4,1,8,5]
let b = fromList [3,3,2,0,1,1,2,2]
let c = fromList [ a ! k | k <- b ]
Expected c = [[7],[4,1],[3,8,5],[9,2]]

我有点卡住,收到错误

  

“无法将预期类型[Int]与实际类型Vector Integer匹配   在stmt list comprehension   k&lt; - b“

4 个答案:

答案 0 :(得分:4)

这不起作用,因为b是Vector而不是列表:

k <- b

但是,这可以起作用:

[ ... | k <- toList b ]

接下来,ab的类型为Vector Integer!运算符的格式为Int。因此,您需要使用fromInteger转换索引:

let c = fromList [ a ! fromInteger k | k <- toList b]

<强>更新

这是一种在不重复传递数组的情况下执行转换的方法:

import Data.List

fst3  (b,_,_) = b
third (_,_,a) = a

doit :: Vector Int -> Vector Int -> [[Int]]
doit av bv = [ map third g | g <- groups ]
  where
    triples = zip3 (V.toList bv) [1..] (V.toList av)
    groups = groupBy (\s t -> fst3 s == fst3 t) $ sort triples

这基本上是Schwartzian Transform,在排序步骤之后添加了groupBy。三元组的排序是以规范的方式完成的 - 第一个坐标后面是第二个坐标,后面是第三个坐标。

还有其他方法可以为groups编写表达式:

import Data.Funcition (on)
import GHC.Exts (groupWith)

    ...
    groups = groupBy (on (==) fst3) $ sort triples
    groups = groupWith fst3 triples

请注意,groupBy要求排序三元组,而groupWith则不排序。

答案 1 :(得分:0)

在ErikR的帮助下,我提出了这个问题:

let c = fromList [fromList [a ! i | i <- [0..Data.Vector.length b-1], (b ! i)==j] | j <- [0..Data.Vector.maximum(b)]]

它有效,但它不漂亮,更好吗?

答案 2 :(得分:0)

看起来你想要的可能是

accumulate (flip (:)) (replicate n []) (zip b a)

...虽然您必须明确计算n,但可能是maximum b + 1

答案 3 :(得分:0)

使用列表这似乎是逻辑

> map (map snd) $ groupBy ((==) `on` fst) $ sortBy (comparing fst) $ zip b a

[[7],[4,1],[3,8,5],[9,2]]