Haskell中如何从列表排除特定元组?以过滤(1,1)为例
解决Haskell列表中过滤掉(1,1)的问题
我明白你的困惑啦!咱们一步步来搞定这个需求~
首先先理清几个关键点:
- 你原代码里的列表推导式
[ (i,j) | i <- [1,2], j <- [1..] ],因为Haskell会先遍历i的第一个值1,然后无限遍历j,所以take 10会直接取前10个i=1的元组,这就是你得到[(1,1),(1,2),...,(1,10)]的原因。 - 你想用
filter来去掉(1,1),思路是对的,但写法需要调整。
方法1:用filter函数实现过滤
filter需要两个参数:一个判断条件函数(输入元素返回Bool),和要过滤的列表。你需要写一个函数来判断元组是否不等于(1,1),可以用lambda表达式来快速实现:
-- 先生成原列表,再过滤,最后取前10个 take 10 $ filter (\(i,j) -> (i,j) /= (1,1)) [ (i,j) | i <- [1,2], j <- [1..] ]
这里的\(i,j) -> (i,j) /= (1,1)是一个lambda函数,它接收一个二元组,判断这个元组是不是不等于(1,1)——符合条件的元素会被保留下来。
方法2:直接在列表推导式中加条件(更简洁)
其实不用额外调用filter,可以直接在列表推导式里添加过滤条件,生成元素时就排除(1,1):
take 10 [ (i,j) | i <- [1,2], j <- [1..], (i,j) /= (1,1) ]
这样写更直观,逻辑和用filter是一样的,只是把过滤逻辑整合到了列表生成的步骤里。
纠正你之前的错误尝试
你写的Filter ((i,j)/=0) "the list"有几个问题:
- Haskell对大小写敏感,函数名
filter必须小写,不能写成Filter; - 判断条件错误:你要排除的是
(1,1),不是0,应该写成(i,j) /= (1,1); - 没有正确绑定元组变量:需要用模式匹配(比如
\(i,j))来取出元组里的i和j,否则Haskell不知道i和j是什么。
运行结果
不管用哪种方法,最终得到的列表都会是:
[(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9),(1,10),(2,1)]
正好10个元素,成功去掉了(1,1)。
内容的提问来源于stack exchange,提问作者StarsLord
相关产品推荐
相关产品推荐

