我正在尝试编写这样的函数:
updateMatrix:: [[a]] -> a -> (x, y) ->[[a]]
这应该包含列表,例如:
[ [1, 2, 3, 4],
[5, 6, 7, 8]]
并将给定元素放在指定的坐标处,因此,给出:
[ [1, 2, 3, 4],
[5, 6, 7, 8]] 9 (0, 1)
它应该返回
[ [1, 9, 3, 4],
[5, 6, 7, 8]]
我不知道如何在不重建整个矩阵的情况下做到这一点,请帮忙!
答案 0 :(得分:6)
您每次都需要重建矩阵。因此,只要您不需要高性能计算,就可以使用这种清晰的实现:
replace :: (a -> a) -> Int -> [a] -> [a]
replace f 0 (x:xs) = (f x):xs
replace f i (x:xs) = x : replace f (i-1) xs
replace f i [] = []
replace2D :: (a -> a) -> (Int, Int) -> [[a]] -> [[a]]
replace2D f (x,y) = replace (replace f y) x
你的职能是:
updateMatrix ll x c = replace2D (const x) c ll
答案 1 :(得分:4)
这是一个实现:
updateMatrix :: [[a]] -> a -> (Int, Int) -> [[a]]
updateMatrix m x (r,c) =
take r m ++
[take c (m !! r) ++ [x] ++ drop (c + 1) (m !! r)] ++
drop (r + 1) m
但也许正如你所说的那样“重建整个矩阵”?注意 列表在Haskell中不可变,因此您无法破坏性地更新 一个条目,如果这是你的意思,而不是“重建整体 矩阵”。
答案 2 :(得分:2)
这是一个简短的:
replace p f xs = [ if i == p then f x else x | (x, i) <- zip xs [0..] ]
replace2D v (x,y) = replace y (replace x (const v))
现在您可以完全按照自己的意愿使用它:
λ → let m = [[1, 2, 3, 4], [5, 6, 7, 8]]
λ → replace2D 9 (0, 1) m
[[1,2,3,4],[9,6,7,8]]
正如其他人已经说过的那样,
m
视为指向链接指针列表的指针,您可以看到为什么它比纯字节流更慢。有更好的库使用更接近后者的东西。m
。您只能使用m
。IORef
一样。但是将它用于此将是错误的。 Stack Overflow上还有许多其他问题,解释了它的用法,优点和缺点。答案 3 :(得分:1)
作为一种纯函数式语言,Haskell要求您在更新项目时返回“全新”矩阵,因此您需要重建整个矩阵(如果您真的对矩阵处理感兴趣,请看一下matrix library而非实施自己的。)
注意,列表不是这种操作的好选择,但是如果你是出于教育目的而做的,首先要实现一个“替换”[a]
中的元素的函数,然后使用它两次(函数组合可以帮助那里)以获得updateMatrix
功能。 Here是一个可以帮助您的答案。