[英]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 !
接下来, a
和b
的类型是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.