说我有一个从2
到20
的所有整数的列表。
[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
我还有一个功能f x
,可以返回True
或False
。当我将此函数应用于位置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]
我们还要说位置4
,8
以及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
是谓词所持有的数字,因为除了2
和3
之外,没有两个连续的整数都是素数,我可以轻松处理我的解决方案。相反,您可以获得的最接近的是[x, t, x, t]
,在这种情况下,我想删除所有这些元素。
答案 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)
是您在过滤时考虑列表的其余部分来过滤列表的方式。很难给出比构成它的功能组合更好的名称。