通过在Haskell中添加列表中的下两个元素的值来修改该列表中的元素

ddrv8njm  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(203)

我想写一个函数来修改列表中的某些元素,只要它们是一个特定的值。
例如,对于每一个等于10的数字,我想把列表中的下两个数字加到原来的数字上。[10、9、1、8、2、10、10、6、4、5、4、7、3、4、3、7、1]
那么我需要一个函数来返回:[20、9、1、8、2、26、20、6、4、5、4、7、3、4、3、7、1]
我已经探索过使用Map来实现这一点,但是我不知道如何使用列表中接下来的两个元素来获得Map,以便将它们添加到我想要修改的元素中。
到目前为止,这是我的代码。我知道它明显有缺陷,因为它重用了x:y:z的不变值

bowling :: [Int] -> [Int]
bowling (x:y:z:xs) = map (\x -> if (x == 10) then x + y + z else x) xs

b1 = bowling [10, 9, 1, 8, 2, 10, 10, 6, 4, 5, 4, 7, 3, 3, 4, 3, 7, 1]

我尝试使用Map来解决这个问题,但是我不知道如何创建一个函数来使用列表中的下两个元素。

yr9zkbsy

yr9zkbsy1#

仅仅用map确实是不可能的,但是可以用显式递归来实现,如下所示:

bowling :: [Int] -> [Int]
bowling [] = []
bowling (x:xs) = case x of
    10 -> case xs of
        y:z:_ -> x + y + z:bowling xs
        _ -> error "Uh oh, got a 10 but one or both of the next two numbers to add were missing"
    _ -> x:bowling xs

如果你真的想用高阶函数来实现这一点,你可以用mapAccumRpara来代替。例如,用mapAccumR

import Data.Traversable (mapAccumR)

bowling :: [Int] -> [Int]
bowling = snd . mapAccumR go (uhoh,uhoh) where
  go :: (Int,Int) -> Int -> ((Int,Int), Int)
  go ~(y,z) x = ((x,y), if x == 10 then x+y+z else x)
  uhoh :: Int
  uhoh = error "Uh oh, got a 10 but one or both of the next two numbers to add were missing"

相关问题