简体   繁体   English

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

[英]replacing an element in a list of lists in haskell

I am trying to write a function like this: 我想写一个这样的函数:

updateMatrix:: [[a]] -> a -> (x, y) ->[[a]]

This is supposed to take in a list of lists such as: 这应该包含一系列列表,例如:

[ [1, 2, 3, 4],
  [5, 6, 7, 8]]

and put the given element at the specified coordinates, so, given: 并将给定元素放在指定的坐标处,因此,给出:

[ [1, 2, 3, 4],
  [5, 6, 7, 8]] 9 (0, 1)

it should return 它应该回来

[ [1, 9, 3, 4],
  [5, 6, 7, 8]]

I can't figure out how to do this without having to rebuild the whole matrix, please help! 我无法弄清楚如何在不重建整个矩阵的情况下做到这一点,请帮忙!

You need to rebuild the matrix every time. 您需要每次都重建矩阵。 So as long as you don't need high performance computing, you could use this legible implementation: 因此,只要您不需要高性能计算,就可以使用这种清晰的实现:

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

Your function would be: 你的功能是:

updateMatrix ll x c = replace2D (const x) c ll

Here's an implementation: 这是一个实现:

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

But maybe this "rebuilds the whole matrix" as you say? 但也许正如你所说的那样“重建整个矩阵”? Note that lists are not mutable in Haskell, so you can't destructively update one entry, if that's what you would mean by not "rebuilding the whole matrix". 请注意,列表在Haskell中是不可变的,因此如果不是“重建整个矩阵”,那么就不能破坏性地更新一个条目。

Here's a short one: 这是一个简短的:

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

Now you can use it exactly like you wanted: 现在您可以完全按照自己的意愿使用它:

 λ →  let m = [[1, 2, 3, 4], [5, 6, 7, 8]]
 λ →  replace2D 9 (0, 1) m
[[1,2,3,4],[9,6,7,8]]

As others already said, 正如其他人已经说的,

  1. This approach is of course rather slow , and only makes sense if the structure is more complex than the lists are long. 这种方法当然相当缓慢 ,只有在结构比列表更长时才更有意义。 There's easy documentation about the internal structure and complexity of things in Haskell out there. 有关Haskell内部结构和事物复杂性的简单文档。
    Think of m as a pointer to a linked list of pointers, and you can see why it's slower than a pure stream of bytes. m视为指向链接列表的指针,您可以看到为什么它比纯字节流慢。 There are better libs that use something closer to the latter. 有更好的库使用更接近后者的东西。
  2. Haskell's values are immutable because there are no side-effects. Haskell的值是不可变的,因为没有副作用。 Which is good for reliability. 这对可靠性有好处。 So you can't change m . 所以你不能改变m You can only build something out of m . 你只能用m构建一些东西。
  3. Haskell can simulate mutable references , with the help of monads. 在monad的帮助下,Haskell 可以模拟可变引用 Like IORef . IORef But using it for this would be rather wrong . 但是将它用于此将是错误的 There are many other questions here on Stack Overflow, explaining its usage, pros and cons. Stack Overflow上还有许多其他问题,解释了它的用法,优点和缺点。

Being a purely functional language, Haskell requires you to return a "brand new" matrix when you update an item, so you need to rebuild the whole matrix indeed (if you're actually interested in matrix processing, cast a look at matrix library rather than implementing your own). 作为一种纯粹的函数式语言,Haskell要求你在更新项目时返回一个“全新的”矩阵,所以你需要重建整个矩阵(如果你真的对矩阵处理感兴趣,那就看一下矩阵库吧而不是实现自己的)。

Beware, lists are not a good choice for such manipulations, but if you do it for educational purposes, start with implementing a function that "replaces" an element in [a] , then use it twice (function composition can help there) in order to get your updateMatrix function. 请注意,列表不是这种操作的好选择,但是如果你是出于教育目的,首先要实现一个“替换” [a]的元素的函数,然后使用它两次(函数组合可以帮助那里)按顺序获取updateMatrix函数。 Here is an answer that can help you on your way. 是一个可以帮助您的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM