如何在Haskell中遍历列表时获取当前元素的前后元素?
如何在Haskell中同时获取列表元素的前序、当前和后序元素?
Haskell标准库中没有直接提供你想要的那种接收三参数lambda的map变体,但可以通过以下几种方式实现需求:
方法1:用zip3组合偏移列表(推荐处理边界情况)
通过构造三个偏移后的列表,再用zip3将它们组合成包含前序、当前、后序元素的三元组列表。为了处理首尾元素没有前序/后序的情况,我们用Maybe类型标记不存在的邻居:
withNeighbors :: [a] -> [(Maybe a, a, Maybe a)] withNeighbors [] = [] withNeighbors list = zip3 prevList curList nextList where prevList = Nothing : map Just (init list) curList = list nextList = map Just (tail list) ++ [Nothing]
使用示例:
-- 处理[1,2,3,4,5] processElements :: [(Maybe Int, Int, Maybe Int)] -> [String] processElements = map (\(prev, cur, next) -> "当前元素: " ++ show cur ++ ", 前序元素: " ++ show prev ++ ", 后序元素: " ++ show next) main = print $ processElements $ withNeighbors [1,2,3,4,5]
输出结果:
["当前元素: 1, 前序元素: Nothing, 后序元素: Just 2", "当前元素: 2, 前序元素: Just 1, 后序元素: Just 3", "当前元素: 3, 前序元素: Just 2, 后序元素: Just 4", "当前元素: 4, 前序元素: Just 3, 后序元素: Just 5", "当前元素: 5, 前序元素: Just 4, 后序元素: Nothing"]
方法2:自定义递归函数(灵活处理边界默认值)
如果不想用Maybe,而是想给首尾元素指定默认的前序/后序值,可以写递归函数:
withNeighbors' :: a -> a -> [a] -> [(a, a, a)] withNeighbors' _ _ [] = [] withNeighbors' prevDef nextDef [x] = [(prevDef, x, nextDef)] withNeighbors' prevDef nextDef (x:y:xs) = (prevDef, x, y) : go x y xs where go prev cur [] = [(prev, cur, nextDef)] go prev cur (n:ns) = (prev, cur, n) : go cur n ns
使用示例:
-- 给首尾指定默认值0 main = print $ withNeighbors' 0 0 [1,2,3,4,5]
输出结果:
[(0,1,2),(1,2,3),(2,3,4),(3,4,5),(4,5,0)]
方法3:滑动窗口方式(利用tails)
通过Data.List.tails生成所有后缀,再提取每个后缀的前三个元素作为窗口,适合需要批量处理连续三元组的场景:
import Data.List (tails) slidingWindow :: [a] -> [(Maybe a, Maybe a, Maybe a)] slidingWindow = map takeWindow . tails where takeWindow [] = (Nothing, Nothing, Nothing) takeWindow [x] = (Nothing, Just x, Nothing) takeWindow [x,y] = (Nothing, Just x, Just y) takeWindow (x:y:z:_) = (Just x, Just y, Just z)
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

