简体   繁体   English

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

[英]Haskell create vector with subvectors using indexes

I'm trying to create a vector with subvectors consisting of elements taken out from another vector using a vector of sub-vector indexes. 我正在尝试创建一个包含子向量的向量,该子向量由使用子向量索引的向量从另一个向量中取出的元素组成。 Each element in b corresponds to the sub-vector-index the elements in a should have when put into c . 中的每个元素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]]

I'm a bit stuck, getting the error 我有点卡住了,得到了错误

"Could not match expected type [Int] with actual type Vector Integer in stmt list comprehension k <- b" “无法在stmt列表理解k <-b中将预期类型[Int]与实际类型Vector Integer匹配”

This doesn't work since b is a Vector, not a list: 这不起作用,因为b是一个Vector,而不是一个列表:

k <- b

However, this can work: 但是,这可以工作:

[ ... | k <- toList b ]

Next, the type of a and b is Vector Integer , and the ! 接下来, ab的类型是Vector Integer ,并且! operator takes an Int . 运算符采用一个Int So you need to convert the index using fromInteger : 因此,您需要使用fromInteger转换索引:

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

Update 更新

Here is a way to perform the transformation without repeated passes over the arrays: 这是一种执行转换而无需重复遍历数组的方法:

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

This is basically a Schwartzian Transform with a groupBy added after the sorting step. 这基本上是Schwartzian变换 ,在排序步骤之后添加了groupBy。 The sorting on the triples is done in the canonical way - a lex sort on the first coordinate followed by the second coordinate followed by the third coordinate. 在三元组上的排序以规范的方式进行-在第一个坐标上进行lex排序,然后在第二个坐标上进行排序,然后在第三个坐标上进行。

There are other ways to write the expression for groups : 还有其他方法可以为groups编写表达式:

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

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

Note that groupBy requires that the triples be sorted whereas groupWith doesn't. 请注意, groupBy要求对三元组进行排序,而groupWith则不需要。

With the help of ErikR I came up with this: 在ErikR的帮助下,我想到了:

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

It works but it's not pretty, any better? 它可以工作,但不是很好,更好吗?

It looks like what you want would probably be 看起来您想要的可能是

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

...although you're going to have to explicitly calculate n , perhaps as maximum b + 1 . ...尽管您将必须显式地计算n ,也许是maximum b + 1

With lists this seems to be the logic 与列表,这似乎是逻辑

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM