Haskell的新手。我已经创建了一个char数组,并试图找出在给定特定索引的情况下修改该数组中数据的最佳方法。
我已经创建了一个数组,该数组将在我的主方法中传递给以下方法。那部分工作正常。我只是无法弄清楚如何处理每个索引处的数据。在这种特殊情况下,如果满足以下条件,则我试图覆盖该值。我想将其返回到主菜单,以便我可以打印出更新后的电路板。
try {
...
} catch {
case _ : Throwable => ... // catch all exceptions
}
答案 0 :(得分:4)
您实际上不需要修改数组。只需让您的函数创建一个具有所需更改的新数组,就像这样:
modifyArray :: Array Int Char -> Int -> Array Int Char
modifyArray arr i =
if i > 0 then
if i `mod` 102 == 1 then
arr // [(i, ' ')]
else modifyArray arr (i-1)
else arr
Data.Array
包含//
运算符,这意味着“取左边的数组,右边应用更改,然后返回结果”。另外,由于此功能不执行任何IO,因此无需在类型签名中使用“ do”或包含IO。
答案 1 :(得分:2)
如果您打算仅更新阵列几次,则可以使用(//) :: Ix i => Array i e -> [(i, e)] -> Array i e
operator,就像@JosephSible所说。
但是,如the question "How fast is Data.Array
?"中所述,如果要频繁更新数组 ,这不是很有效:
请注意,
//
可能是 O(n),因为它必须遍历列表(就像命令式程序一样)。如果您需要大量的突变,则可以使用MArray
或MVector
。
因此,这意味着对于大型数组,更新数组可能会花费一些时间,因为每次更新都会导致对原始数组进行复制并修改该特定值。
IOArray
是此类MArray
的特定类型。因此,我们可以用writeArray :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
定义modifyArray
:
modifyArray :: IOArray Int Char -> Int -> IO (IOArray Int Char)
modifyArray arr idx | i < 0 = return arr
| mod i 102 == 1 = writeArray arr idx ' ' >> return arr
| otherwise = modifyarr arr idx
请注意,这里不必返回数组,从本质上讲,IOArray
可以看作是对可变数组的引用,因此在writeArray
操作之后,arr
指的是修改后的数组。如果您在较大的IO
操作中使用此数组,则在modifyArray
之后,将修改该数组。
您在此处使用循环来获取具有i
且小于或等于初始索引的最大索引div i 102 == 1
。但是,您可以通过减去模的结果来改善这一点:
modifyArray :: IOArray Int Char -> Int -> IO (IOArray Int Char)
modifyArray arr idx | i < 0 = return arr
| otherwise = writeArray arr (idx - mod (idx-1) 102) ' ' >> return arr