Haskell如何实现从列表中移除第N个奇数的功能
实现Haskell移除列表第N个奇数的函数
我们需要实现的removeOdd函数逻辑为:遍历列表时计数遇到的奇数,删除第N个命中的奇数,其余元素保持原有顺序不变,符合示例removeOdd 2 [2,4,3,6,5,8] == [2,4,3,6,8]。
基础递归实现(最易理解)
代码如下:
removeOdd :: Int -> [Int] -> [Int] -- 空列表直接返回 removeOdd _ [] = [] removeOdd n (x:xs) -- 当前元素为偶数,直接保留,继续遍历剩余元素 | even x = x : removeOdd n xs -- 当前元素为奇数 | otherwise = if n == 1 -- 刚好是要删除的第N个奇数,跳过当前元素,剩余元素直接返回 then xs -- 不是目标奇数,保留当前元素,计数减1继续遍历 else x : removeOdd (n - 1) xs
测试验证:运行removeOdd 2 [2,4,3,6,5,8],输出结果为[2,4,3,6,8],和预期完全一致。
边界处理增强版
如果需要对非法输入做校验,比如N为非正整数的场景,可以添加参数判断:
removeOdd :: Int -> [Int] -> [Int] removeOdd n xs | n <= 0 = error "参数N必须为正整数" | otherwise = go n xs where go _ [] = [] go cnt (x:rest) | even x = x : go cnt rest | otherwise = if cnt == 1 then rest else x : go (cnt - 1) rest
无显式递归的函数式写法
如果偏好使用高阶函数组合实现,可以用以下写法:
removeOdd :: Int -> [Int] -> [Int] removeOdd n xs = map snd $ filter filterRule $ zip oddIndex xs where -- 为每个元素标注当前累计遇到的奇数个数 oddIndex = tail $ scanl (\acc x -> if odd x then acc + 1 else acc) 0 xs -- 过滤规则:偶数全部保留,奇数只排除序号等于N的 filterRule (idx, val) = even val || idx /= n
内容的提问来源于stack exchange,提问作者123
相关产品推荐
相关产品推荐

