我想知道在维修中是否存在(//)的类似物?
无法并行化的数组转换需要它。例如,如果函数需要整个数组更改数组的单个条目,而不是将其应用于新数组等等(并且应该按顺序运行)。
答案 0 :(得分:5)
(//)
可以用Data.Array.Repa.fromFunction实现:
import Data.Array.Repa
(//) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(//) arr us = fromFunction (extent arr) (\sh -> case lookup sh us of
Just a -> a
Nothing -> index arr sh)
fromFunction
可以传递Shape sh => s -> a
类型的函数,它本身可以使用整个数组。
上述实现一次性执行所有更新。
答案 1 :(得分:4)
(//)的一个潜在问题是它需要在列表中向下搜索以找到每个元素的值。如果数组或列表很大,这可能会很昂贵。
另一种选择是利用Data.Vector中的一个方便的功能:
modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
如果安全,可以进行更新。像
这样的东西import Data.Vector.Unboxed as V
import Data.Vector.Mutable.Unboxed as M
import Data.Array.Repa as R
(///) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(///) arr us = R.fromVector sh . modify f $ R.toVector arr
where
sh = extent arr
f mv = forM_ us $ \(k,x) -> do
M.write mv (R.toIndex sh k) x
在我的笔记本电脑上,我测试了一个100万元素的DIM1阵列,更新了100个条目,并获得了以下时间: (//):3.598973 (///):2.0859999999999997e-3