我有一个非常大的Vector a,我想在一个小范围内映射一个函数。例如,如果我有一个大小为1000的Vector,我想将函数f映射到索引100-200处的值,然后返回整个更新的Vector。做这个的最好方式是什么。我对其他数据结构持开放态度,但我不想使用可变向量。
编辑: 这是命令式代码中的等价物。
for (int i = startIdx; i < endIdx ; i++){
bigVector[i] = myFunction(bigVector[i]);
}
答案 0 :(得分:3)
“vector”包的不可变向量实现基本上是一个数组。这意味着对它的任何修改操作都需要遍历整个数组。这种限制并不符合您提到的要求。
由于您说您可以选择不同的数据结构,因此首先需要考虑的是由Array-Mapped Trie算法驱动的数据结构。该算法允许您投影数据结构的片段,连接,删除/获取,追加/前置 - 所有这些都是在常量或对数时间内。它的效率在生产中得到了证明,它推动了Clojure和Scala等语言无处不在的不可变矢量数据结构。
幸运的是,Haskell也有一个实现。它由the "persistent-vector" package呈现,以下是您如何使用它有效地解决问题:
mapOverSlice :: Int -> Int -> (a -> a) -> Vector a -> Vector a
mapOverSlice startIndex length mapper input =
let
(split1Heading, split1Trail) =
splitAt startIndex input
(split2Heading, split2Trail) =
splitAt (pred length) split1Trail
in
split1Heading <>
map mapper split2Heading <>
split2Trail
答案 1 :(得分:0)
像
这样的东西maprange :: (a -> a) -> [a] -> Int -> Int -> [a]
maprange f vector skip nb = (take skip vector) ++ (map f (take nb (drop skip vector))) ++ (drop (skip + nb) vector)
然后像
一样使用它*Main> maprange (\x -> 2*x) [1 .. 10] 3 4
[1,2,3,8,10,12,14,8,9,10]
将前3个元素后的4个元素加倍。
答案 2 :(得分:0)
一种方法是
实施非常简单:
maprange :: (a -> a) -> [a] -> Int -> Int -> [a]
maprange f vector skip nb = map (\(idx,v) -> if idx > skip && idx <= skip+nb then f v else v) zipped_vector
where zipped_vector = zip [1..] vector
复杂性应该是O(n),其中n是原始向量的大小(虽然我不是100%确定zip的复杂性);如果你需要更高效的东西,你应该调查Nikita Volkov在答案中提到的数据结构。