当n适合谓词时,删除Haskell列表中位置n和n-1处的元素

时间:2014-01-17 12:03:18

标签: list haskell predicate

说我有一个从220的所有整数的列表。

[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

我还有一个功能f x,可以返回TrueFalse。当我将此函数应用于位置n的元素并且它等于True时,我想删除它及其先前元素(位置n-1处的元素)。我想继续这样做,直到列表中没有函数等于True的元素,以及它们的前面元素。

实施例: 让我们说位置11的元素(等于13)符合谓词。然后,我想删除10位置的元素,该元素也等于12。之后,我的最终名单将是:

[2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20]

我们还要说位置48以及15中的元素是唯一适合的元素(除了位置13的元素外)谓语。删除它们及其前面的元素后,我的最终列表将如下所示:

[2,3,4,7,8,11,14,15,18,19,20]

我是一个没有经验的Haskell程序员,只是为了好玩而玩。我想过使用某种lambda函数作为过滤器的谓词,或创建像listRemove xs ys这样的函数来删除xs的所有元素,这些元素也是ys的元素,但我觉得两种都失去了。

任何帮助将不胜感激!

编辑:我要做的是解决Project Euler问题,即#179。谓词f x用于检查x是否为素数。因此,我可以肯定地说没有角落案例 - 例如没有[x, x, t, t]这样的情况,其中t是谓词所持有的数字,因为除了23之外,没有两个连续的整数都是素数,我可以轻松处理我的解决方案。相反,您可以获得的最接近的是[x, t, x, t],在这种情况下,我想删除所有这些元素。

2 个答案:

答案 0 :(得分:1)

解决 “删除Haskell列表中位置n和n-1处的元素,当n符合谓词”

filter' :: (a -> Bool) -> [a] -> [a]
filter' f xs = map (\i -> xs!!i) $
                 [i | i <- [0 .. s], fit i && (i >= s || fit (i+1))]
               where s = length xs - 1
                     fit i = not (f (xs!!i))

使用

*Main> filter' (==4) [1,2,3,4,5,6]
[1,2,5,6]

*Main> filter' (\n -> n `mod` 7 == 0) [1..23]
[1,2,3,4,5,8,9,10,11,12,15,16,17,18,19,22,23]

*Main> filter' (\n -> n `elem` [4,5,6]) [1..10]
[1,2,7,8,9,10]

O(n)成本可能

filter' :: (a -> Bool) -> [a] -> ([a], Bool)
filter' _  [] = ([], False)
filter' f [x] = if f x then ([], True) else ([x], False)
filter' f (y:xs) = case filter' f xs of
                    (xs', True)  -> (xs', f y)
                    (xs', False) -> if f y then (xs', True) else (y:xs', False)

使用标准功能

filter' f xs = filter (not.f) $ map fst $ filter (not.f.snd) $ zip xs $ tail xs ++ [last xs]

答案 1 :(得分:1)

假设你有:

disallowed :: Int -> bool
-- A function that matches your example
disallowed x = elem x [6, 10, 13, 17]

你想要的只是

import Data.List (tails)

map head . filter (not . any disallowed . take 2) . filter (not . null) . tails $ [2..20]

如果你想给它一个名字:

filterWithTails :: ([a] -> Bool) -> [a] -> [a]
filterWithTails f = map head . filter f . filter (not . null) . tails

filterWithTails (not . any disallowed . take 2) [2..20]

(not . any disallowed . take 2)是您在过滤时考虑列表的其余部分来过滤列表的方式。很难给出比构成它的功能组合更好的名称。