过滤Haskell中列表列表中的元素

时间:2017-05-20 22:18:40

标签: list haskell filter

我建立了这个结构的列表:

[(Interger, Double)]

List是使用整数列表上的zip和完全相同大小的双打列表创建的。

现在我想过滤掉< 18.5或> 25的双打列表。我遇到的问题是我无法访问双打在过滤功能中使用它们。

这可能很容易,但我是这种语言的血腥菜鸟。我搜索了很多并阅读了其他一些帖子,但我找不到答案。

我得到了:

filter (<18.5) listexpression

所以我正在努力的是那种倾听。如果它是单个值的列表,那很容易。我可以在压缩之前进行过滤,但之后我无法将已过滤列表中的数据连接到其他未过滤的列表。

编辑:我忘了提。这是一张工作表。我们被要求自己构建过滤器和映射函数,不允许对基本Haskell使用任何添加。意思是不允许进口。

4 个答案:

答案 0 :(得分:5)

您可以这样做:

Prelude> filter (\p -> (snd p) < 18.5 || (snd p) > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]

传递给filter的{​​{3}},即

(\p -> (snd p) < 18.5 || (snd p) > 25)

表示对于每pp的第二个元素必须小于18.5或超过25。

或者,您可以像这样写

Prelude> filter (\(_, f) -> f < 18.5 || f > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]

此函数表示,对于第一个值不重要而第二个值为f的任何一对,f必须小于18.5或超过25。

答案 1 :(得分:2)

很高兴看到Ami Tavory's answer解决了您的问题。

但根据这个答案,你评论道:

  

我尝试使用(!!)的组合访问它,但是没有用。

凭借助教[:D]的洞察力,我猜你在Haskell中将listtuple混淆了。

zip返回list tuple,而(!!)list作为(第一个)参数(因此(!!1)取一个list(!!1)个参数),因此list无法应用于zip返回的tuple元素,其类型为Prelude> :t zip zip :: [a] -> [b] -> [(a, b)] Prelude> :t (!!) (!!) :: [a] -> Int -> a Prelude> :t (!!1) (!!1) :: [a] -> a 。< / p>

fst

您已经知道sndtuple已应用于Prelude> :t fst fst :: (a, b) -> a Prelude> :t snd snd :: (a, b) -> b

cnumber

答案 2 :(得分:1)

使用无点样式的紧凑版本将是

 filter ((>18.5).snd) listexpression

这使用函数组合运算符.,其读作:首先将snd函数应用于列表中的元组以提取第二个值,然后将比较应用于此值的18.5。

答案 3 :(得分:0)

仅针对各种各样的信息以及一些不会咬人的信息......

在哈斯克尔the list type is an instance of Monad class。因此,像filter这样的列表操作可以简单地由monadic绑定运算符实现。

*Main> [(1,2.3),(3,21.2),(5,17.1),(4,24.4)] >>= \t -> if snd t < 25 && snd t > 18.5 then [t] else []
[(3,21.2),(4,24.4)]

Monad就是以顺序方式处理所包含的数据。在列表monad中,包含的数据是列表本身的值。因此,绑定运算符可以非常方便地以顺序方式访问monadic值(元组列表)的包含值(元组)。

(>>=) :: Monad m => m a -> (a -> m b) -> m b

monadic绑定运算符的类型签名声明它将monad类型值m a作为第一个参数(此处为元组列表),并将函数作为第二个参数,它接受纯值并返回monadic value(取一个元组并在列表中返回一个元组或在这种情况下返回一个空列表)。

\t -> if snd t < 25 && snd t > 18.5 then [t] else []

了解列表项如何以及为何一个接一个地应用于提供的函数至关重要。整个列表是一个monadic值,并且绑定运算符访问的包含值将传递给提供的a -> m b(采用纯值并返回monadic值)类型函数。因此,应用于此函数的所有列表项都变为monadic值(如果条件满足则为[t],如果失败则为[]),然后由bind运算符连接以形成一个monadic返回值(in这种情况下的元组列表满足lambda函数中实现的条件。

此monadic操作也可以使用do符号

实现
do
t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)]
if snd t < 25 && snd t > 18.5 then return t else []

[(3,21.2),(4,24.4)]

当然,这非常类似于列表推导,这实际上是monadic列表操作的语法糖。因此,让我们通过使用列表推导来最终实现它。

*Main> [t | t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)], snd t < 25 && snd t > 18.5]
[(3,21.2),(4,24.4)]