Haskell问题:如何获取列表中大于左右邻居的元素列表
解决Haskell提取列表峰值元素的问题
嘿,我来帮你搞定这个问题!你要做的是从Integer列表里找出那些严格大于左右两个邻居的元素(也就是“峰值”),比如输入[0,1,5,2,3,7,8,4]要得到[5,8]对吧?你的代码返回空列表,大概率是没有正确处理“同时查看当前元素和左右邻居”的逻辑,我给你拆解一下正确的实现思路和代码:
核心思路:滑动三元组筛选
要找峰值,我们需要每次同时观察三个连续元素:前一个、当前、后一个。Haskell里可以用zip3函数把原列表、原列表的尾部、原列表尾部的尾部组合起来,这样就能得到一组组(prev, curr, next)的三元组,然后只筛选出curr比prev和next都大的情况,再提取curr即可。
简洁的列表推导式实现
findPeaks :: [Integer] -> [Integer] findPeaks xs = [ curr | (prev, curr, next) <- zip3 xs (tail xs) (tail $ tail xs), curr > prev, curr > next ]
测试一下:
> findPeaks [0,1,5,2,3,7,8,4] [5,8]
完全符合你的预期!
递归版本(帮助理解底层逻辑)
如果你想更清楚地理解递归处理的过程,也可以写一个递归实现:
findPeaksRec :: [Integer] -> [Integer] findPeaksRec [] = [] -- 空列表直接返回空 findPeaksRec [_] = [] -- 单个元素没有邻居,返回空 findPeaksRec [_,_] = [] -- 两个元素也没有完整的左右邻居,返回空 findPeaksRec (a:b:c:rest) | b > a && b > c = b : findPeaksRec (b:c:rest) -- b是峰值,加入结果继续处理后续 | otherwise = findPeaksRec (b:c:rest) -- 不是峰值,继续向后遍历
你可能踩的坑
- 边界条件处理错误:如果你的代码没有考虑列表长度小于3的情况,可能会触发错误或者返回空;
- 三元组组合错误:比如没有正确用
zip3把三个偏移后的列表组合,导致拿到的邻居元素不对; - 过滤条件写反:比如把
curr > prev写成了prev > curr,自然筛选不到任何元素。
内容的提问来源于stack exchange,提问作者dziulis
相关产品推荐
相关产品推荐

