首页 > 解决方案 > 如何在haskell中使用特定索引在二维列表中添加一个数字

问题描述

我是haskell的初学者,我尝试在具有特定索引的二维列表中添加一个数字,但我不知道该怎么做

例如我有这个:

[[],[],[]]

我想像这样在索引 1 中放一个数字 (3)

[[],[3],[]]

我试过这个

[array !! 1] ++ [[3]]

但它不起作用

标签: listhaskell

解决方案


到目前为止,您可能已经注意到,Haskell 与许多其他语言不同,因为它通常是不可变的,因此尝试更改值,尤其是在像这样的深度嵌套结构中,并不是最简单的事情。[array !! 1]会给你一个嵌套列表[[]],但这不是可变的,所以你对这个结构所做的任何操作都不会反映在原始列表array中,它将是一个单独的副本。

(有专门的环境可以在其中进行局部可变性,例如 ST monad 中的 Vectors,但这些是一个例外。)

对于您要尝试做的事情,您必须解构列表以使其达到可以轻松进行修改的程度,然后从(修改后的)部分重建最终结构。

splitAt函数看起来可以帮助您:它需要一个列表并将其分成两部分,在您给它的索引处。

let array = [[],[],[]]
splitAt 1 array

会给你

([[]], [[],[]])

这可以帮助您更接近您想要的列表,即中间嵌套列表。

让我们做一个解构绑定,以便以后能够重建您的最终列表:

let array = [[],[],[]]
    (beginning, end) = splitAt 1 array

接下来,您需要获取所需的子列表,这是end列表中的第一项:

    desired = head end

现在您可以进行修改了——注意,这将生成一个新列表,它不会修改那里的列表:

    desired' = 3:desired

现在我们需要把它放回end列表中。不幸的是,end列表仍然是 的原始值[[],[]],所以我们必须用我们的替换它的头部desired'以使其正确:

    end' = desired' : (tail end)

这将删除开头的空子列表并将修改后的列表附加在其位置。

现在剩下的就是将修改后的内容end'与原始内容重新组合beginning

in beginning ++ end'

制作整个片段:

let array = [[],[],[]]
    (beginning, end) = splitAt 1 array
    desired = head end
    desired' = 3:desired
    end' = desired' : (tail end)
in beginning ++ end'

或者,如果您在 REPL 中将所有这些作为命令输入:

let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'

推荐阅读