Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Haskell-通过比较筛选列表_List_Haskell_Compare - Fatal编程技术网

List Haskell-通过比较筛选列表

List Haskell-通过比较筛选列表,list,haskell,compare,List,Haskell,Compare,我需要用Haskell中的掩码筛选列表 它将函数应用于掩码列表的一个元素和数据列表中的对应元素,如果函数返回true,则数据列表中的对应元素将包含在返回的列表中 例如,假设我要筛选出大于掩码项的数据项: filtermask (\m d -> d > m) [1, 5, 7] [5, 6, 7]→[5, 6] 这个问题的任何可能的解决方案都将是梦幻般的。到目前为止,我只做了 filtermask f m d = f m d 这是真的 编辑:解决方案,感谢Tikhon的帮助: f

我需要用Haskell中的掩码筛选列表

它将函数应用于掩码列表的一个元素和数据列表中的对应元素,如果函数返回true,则数据列表中的对应元素将包含在返回的列表中

例如,假设我要筛选出大于掩码项的数据项:

filtermask (\m d -> d > m) [1, 5, 7] [5, 6, 7]→[5, 6]
这个问题的任何可能的解决方案都将是梦幻般的。到目前为止,我只做了

 filtermask f m d = f m d
这是真的

编辑:解决方案,感谢Tikhon的帮助:

filtermask f [] [] = []
filtermask f (fm:rm) (fd:rd)
  |f fm fd = fd:filtermask f rm rd
  |otherwise = filtermask f rm rd

基本上,您要做的是首先将掩码的每个元素与列表的一个元素配对。我们可以使用
zip
,它为我们提供了一个配对列表

现在我们有了一个对列表,我们希望使用比较函数(
,或其他任何函数)对其进行过滤。
函数的类型为
Ord o=>o->o->Bool
;我们需要将其转换为一个接受元组的函数。幸运的是,我们可以用
uncurry
做到这一点
uncurry(>)
为我们提供了一个类型为
Ord o=>(o,o)->Bool的函数

因为我们已经有了一个对的列表,我们可以使用这个函数来过滤它。现在我们有了一个列表,其中只列出了我们想要保留的配对;我们需要一个元素列表。我们可以通过在列表上映射像
fst
这样的投影函数来实现这一点

综上所述,我们得到:

filterMask :: (o -> o -> Bool) -> [o] -> [o] -> [o]
filterMask fn mask list = map fst (filter (uncurry fn) (zip list mask))
还有一个更微妙的技巧:如果掩码比我们的输入列表短,会发生什么?使用此函数,输入列表的其余部分将被抛出。如果这不是你想要的,你需要重复面具。我们可以通过一个名为
cycle
的简洁函数来实现这一点,它会永远重复一个列表。因此,该版本将是:

filterMask fn mask list = map fst (filter (uncurry fn) (zip list (cycle mask)))

由于您的问题是设计,两个相同大小的列表,以及一个正在工作的函数和它们的元素,使用zip函数是一个很好的起点。像这样的工作

# zip [1,2,3] [4,5,6] 
[(1,4),(2,5),(3,6)]
然后,对于每个元组,必须检查谓词是否为fill。
这就像用一个函数应用一个zip,有一个函数

# zipWith (\x y -> x + y) [1,2,3] [4,5,6] 
[5,7,9]
但是,应用的功能比提供的功能更多。
如果谓词不满足,我们该怎么办?
这两点由条件语句和
类型管理。
最后我们得到一个列表,其中包含两种值,一种是零,另一种是x,我们希望保留最后一个值
catMaybe
完成这项工作

# filtermask f m d = catMaybes $ zipWith (\x y -> if f x y then Just y else Nothing) m d

问题应分为两部分:

  • 通过比较两个列表生成布尔掩码
  • 基于布尔掩码筛选其中一个列表
  • 对于1,您可以使用
    zipWith
    。对于2,您可以使用
    maskFilter

    maskFilter :: [Bool] -> [a] -> [a]
    maskFilter mask xs = [x | (m,x) <- zip mask xs, m]
    

    您的掩码和数据项是否总是列表且大小相同?出于我的目的,是的,它们将具有相同的大小,并且将是列表:)这非常有助于提出更准确地满足要求的解决方案。非常感谢你,我从你的解决方案中学到了很多。我对问题进行了编辑,以包含项目最终接受的解决方案,我接受了您的回答:)谢谢!太棒了,这看起来很像最终的解决方案。谢谢!
    let
        xs = [1,5,7]
        ys = [5,6,7]
        mask = zipWith (>) ys xs
    in
        maskFilter mask ys