替换haskell中列表列表中的元素

时间:2013-11-22 23:00:10

标签: list haskell

我正在尝试编写这样的函数:

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]]

我不知道如何在不重建整个矩阵的情况下做到这一点,请帮忙!

4 个答案:

答案 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]]

正如其他人已经说过的那样,

  1. 这种方法当然是,只有在结构比列表更长时才更有意义。有关Haskell中内部结构和事物复杂性的简单文档。
    可以将m视为指向链接指针列表的指针,您可以看到为什么它比纯字节流更慢。有更好的库使用更接近后者的东西。
  2. Haskell的值是不可变的,因为没有副作用。这对可靠性有好处。所以你不能改变m。您只能使用m
  3. 构建内容
  4. Haskell 可以在monad的帮助下模拟可变的引用。像IORef一样。但是将它用于此将是错误的。 Stack Overflow上还有许多其他问题,解释了它的用法,优点和缺点。

答案 3 :(得分:1)

作为一种纯函数式语言,Haskell要求您在更新项目时返回“全新”矩阵,因此您需要重建整个矩阵(如果您真的对矩阵处理感兴趣,请看一下matrix library而非实施自己的。)

注意,列表不是这种操作的好选择,但是如果你是出于教育目的而做的,首先要实现一个“替换”[a]中的元素的函数,然后使用它两次(函数组合可以帮助那里)以获得updateMatrix功能。 Here是一个可以帮助您的答案。