Haskell 按索引更新子列表

Amo*_*moz 2 haskell

在尝试学习 Haskell 时,我最近几次遇到过这个简单的模式:

假设我有一个列表,我想更新子列表中的所有元素,例如从索引 i 到 j。

我能想到的所有解决方案都让人感觉非常糟糕和糟糕,就像这个例子:

import qualified Data.Sequence as S

increment :: Int -> Int -> S.Seq Int -> S.Seq Int
increment i j sq | i <= j = increment (i + 1) to (S.adjust (+1) i sq)
                 | otherwise = sq
Run Code Online (Sandbox Code Playgroud)

我想如果我列出一份清单的话,情况会变得更糟。

有人知道一些简单的方法可以做到这一点吗?我尝试过搜索,也查看了标准库(Data.Array、Data.Vector 等),但它的编写方式有些让我的眼睛流血,我需要一些人性化的建议

ass*_*.jc 5

我尝试过搜索,也查看了标准库(Data.Array、Data.Vector 等),但它的编写方式有些让我的眼睛流血,我需要一些人性化的建议

Data.Array是的,对于涉及索引的问题,可以直接使用对偶。对于不可变数组,您可以使用accum函数通过对列表来更新数组元素(index, value)以指定索引和值。

例如,假设我们需要将 1 添加到[1,2,3,4,5,6,7,8,9,10]索引 2 到 4 的数组元素中。

首先,从 list 构造一个数组[1,2,3,4,5,6,7,8,9,10]

testArray = let xs = [1..10] in listArray (0, length xs-1) xs
Run Code Online (Sandbox Code Playgroud)

并将accum函数应用于数组:

increment' i j ary = accum (+) ary (zip [i..j] (repeat 1))
Run Code Online (Sandbox Code Playgroud)

请注意,(zip [i..j] (repeat 1))构造一个对的列表,如果i = 2 and j = 4给出:

[(2, 1), (3, 1), (4, 1)]
Run Code Online (Sandbox Code Playgroud)

pair 的第一个值是数组的索引,第二个是 的第二个参数(+)accum检索特定索引的值并应用于(+1)该值,这正是我们想要的。要测试它:

elems $ increment' 2 4 testArray
Run Code Online (Sandbox Code Playgroud)

给出

[1,2,4,5,6,6,7,8,9,10]
Run Code Online (Sandbox Code Playgroud)

否则,如果您只想用新值替换数组的旧值,而不关心旧值是什么。accum函数也可以应用在这种情况下。例如,假设将索引 2 到 4 的元素替换为0

accum (flip const) testArray (zip [2..4] (repeat 0))
Run Code Online (Sandbox Code Playgroud)