Haskell:列表中满足谓词的最高序列

时间:2019-02-08 09:06:59

标签: haskell functional-programming sequence

我想要一个带有签名takeUntill的函数takeUntill :: (Int -> Bool) -> [Int] -> [Int]。我确实实现了该实现,但是我正在寻找一种比现有问题更干净的解决方案。 我当前的解决方案是:

takeUntill :: (Int -> Bool) -> [Int] -> [Int]
takeUntill p a = snd $ maximum $ [(length x, x) | x <- groups p a]
groups :: (Int -> Bool) -> [Int] -> [[Int]]
groups _ [] = []
groups p a = ((takeWhile p a):(groups p (drop 1 $ dropWhile p a)))

1 个答案:

答案 0 :(得分:3)

我认为您执行此操作的方式看起来不错,但是groups函数很杂乱-特别是您在每一步中从不满足p的元素中精确地删除1的方式,这可能会导致结果里面有很多多余的空列表。 (只要takeUntil的至少1个元素满足a,这些当然不会影响p,但它们仍然存在。)

我将使用一些有用的库函数按如下方式重写groups

groups p a = filter (p . head) $ groupBy ((==) `on` p) a

我不知道它是否更有效,但是我当然觉得它更容易阅读。为了提供一些解释,groupByhttp://hackage.haskell.org/package/base-4.12.0.0/docs/Data-List.html#v:groupBy)来自Data.List,并根据两个连续参数的函数是否为真将列表分为子列表列表。 onhttp://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Function.html#v:on)是Data.Function中一个方便的小函数,它将另一个函数的结果馈入二进制函数的输入。结果是

groupBy ((==) `on` p) a

将列表分为几部分,其中p始终为True或始终为False。然后,我们将其过滤为真实的部分。