You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell列表元素修改:匹配10时累加后续两个元素

Haskell: 替换列表中等于10的元素为自身加后续两个元素之和

问题分析

你需要遍历列表,将每个等于10的元素替换为10 + 下一个元素 + 下下个元素,其余元素保持不变。map函数无法满足需求,因为它只能单独处理每个元素,无法获取当前元素的后续元素上下文;且你原代码中的x:y:z仅绑定了列表前三个元素,遍历后续元素时会重复使用这三个值,导致逻辑错误。

递归实现方案

递归是处理Haskell列表问题的自然方式,我们可以在遍历过程中携带后续元素的信息,分情况处理:

bowling :: [Int] -> [Int]
-- 空列表直接返回空
bowling [] = []
-- 只有一个元素,无法获取后续两个元素,直接返回
bowling [x] = [x]
-- 只有两个元素,同样无法满足"加后续两个元素"的条件,直接返回
bowling [x, y] = [x, y]
-- 列表长度≥3时,分情况处理第一个元素
bowling (x:y:z:xs)
  | x == 10  = (x + y + z) : bowling (y:z:xs)  -- x是10,替换为x+y+z,继续处理剩余列表
  | otherwise = x : bowling (y:z:xs)            -- x不是10,直接保留,继续处理剩余列表

代码验证

用你的测试输入验证:

b1 = bowling [10, 9, 1, 8, 2, 10, 10, 6, 4, 5, 4, 7, 3, 3, 4, 3, 7, 1]
-- 输出:[20,9,1,8,2,26,20,6,4,5,4,7,3,3,4,3,7,1]

完全符合预期结果。

原代码问题解析

你的原代码:

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

存在两个核心问题:

  1. 上下文丢失:map遍历的是xs(原列表去掉前三个元素后的部分),lambda中的x是xs的元素,但y和z始终是原列表的第二个和第三个元素,导致所有等于10的元素都会加上这两个固定值,而非自身的后续两个元素。
  2. 截断列表:返回结果仅包含xs处理后的元素,原列表的前三个元素被直接丢弃,导致输出长度比输入短。

可选实现(zipWith3)

如果喜欢更简洁的写法,可以用zipWith3将原列表与它的两次tail结果绑定,生成三元组后处理:

bowling :: [Int] -> [Int]
bowling lst
  | length lst < 3 = lst
  | otherwise = take (length lst) $ zipWith3 modify lst (tail lst) (tail $ tail lst) ++ drop 2 lst
  where
    modify x y z = if x == 10 then x + y + z else x

不过这种方式需要处理列表长度不足3的情况,且因为用到了length和take,对于超长列表的效率不如递归实现。

内容的提问来源于stack exchange,提问作者JSchofi95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:30:44