Если вы планируете обновить массив только несколько раз, вы можете использовать оператор (//) :: Ix i => Array i e -> [(i, e)] -> Array i e
, как говорит @ JosephSible .
Как, однако, обсуждается в вопрос " Как быстро Data.Array
? " , это не очень эффективно, если вы хотите регулярно обновлять массив :
Обратите внимание, что //
, вероятно, O (n) , хотя, поскольку он должен проходить по списку (точно так же, как это делает императивная программа).Если вам нужна большая мутация, вы можете использовать MArray
или MVector
.
Таким образом, это означает, что для больших массивов обновление массива может занять некоторое время, так каккаждое обновление приводит к созданию копии исходного массива и изменению этого конкретного значения.
IOArray
- это определенный типтаких MArray
.Таким образом, мы можем определить modifyArray
с помощью writeArray :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
:
modifyArray :: <b>IOArray</b> Int Char -> Int -> IO (<b>IOArray</b> Int Char)
modifyArray arr idx | i < 0 = return arr
| mod i 102 == 1 = <b>writeArray arr idx ' '</b> >> 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 <b>(idx - mod (idx-1) 102)</b> ' ' >> return arr