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

如何用Haskell列表推导式生成列表[1,2,5,6,9,10,13,14,17,18]?

解决Haskell列表推导式生成目标列表的问题

你的问题很典型——列表推导式里的生成器和过滤条件搞混了,导致结果重复。先帮你理清楚:

为什么你的代码会得到重复结果?

你写的代码:

[x | x <- [1..18], y <- [1..4], y < 3]

这里的y <- [1..4]是生成器,意味着对于每个x,Haskell会遍历y的所有值(1、2、3、4),然后筛选出y < 3的情况(也就是y=1和y=2)。所以每个x会被生成两次,最终结果里每个数都重复了,这显然不是你想要的。

用列表推导式生成目标列表的正确方式

首先先看目标列表[1,2,5,6,9,10,13,14,17,18]的规律:每4个数里取前两个(1-4取1、2,5-8取5、6,以此类推)。基于这个规律,我们可以直接在过滤条件里判断x是否符合这个规则。

方法1:用取模运算过滤

最直接的写法是检查x除以4的余数是1或2:

[x | x <- [1..18], x `mod` 4 `elem` [1, 2]]

或者换一种更简洁的取模判断:

[x | x <- [1..18], (x - 1) `mod` 4 < 2]

这两种写法都能精准筛选出你要的数,运行后就能得到目标列表。

方法2:用分组思路(结合列表推导式)

如果你想更直观地体现“每4个取前两个”的逻辑,也可以先把列表分成每4个一组,再取每组前两个,最后拼接。虽然用到了concat,但核心还是列表推导式:

concat [take 2 group | group <- chunksOf 4 [1..18]]

不过这个需要先导入Data.List.Split模块(import Data.List.Split),如果不想额外导入模块,方法1更合适。

额外:如果一定要用y辅助过滤(不推荐,但可以演示)

如果你坚持想用y来参与过滤逻辑(虽然没必要),可以把y的判断放在过滤条件里,而不是作为生成器。比如:

[x | x <- [1..18], any (\y -> y < 3) [1..(x `mod` 4)]]

但这种写法可读性差,不如直接用取模的方式清晰,所以不推荐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:18:39