如何编写一个takeWhile来保持第一个与条件不匹配的元素?
示例(显然我的例子比这更棘手):
而不是takeWhile (\× - > x! = 3) [1..10]
返回[1,2]
我需要[1,2,3]
。
我想到了(takeWhile myFunc myList) ++ [find myFunc myList]
,但这意味着我需要通过我的清单2次......
有什么想法吗?
答案 0 :(得分:9)
您可以使用span
或break
。
λ> span (/=3) [1..10]
([1,2],[3,4,5,6,7,8,9,10])
所以你可以这样做:
takeWhileInc :: (a -> Bool) -> [a] -> [a]
takeWhileInc p xs = case zs of [] -> error "not found"
(z:_) -> ys ++ [z]
where
(ys, zs) = span p xs
(或者当zs
为空时你想要发生什么,因为没有3
被发现了。)
答案 1 :(得分:7)
你可以自己动手。
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p = foldr (\x ys -> if p x then x:ys else [x]) []
将其与
进行比较takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p = foldr (\x ys -> if p x then x:ys else []) []
显式递归对此也没问题。
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p [] = []
takeWhileOneMore p (x:xs) =
if p x
then x : takeWhileOneMore p xs
else [x]
答案 2 :(得分:0)
我更喜欢使用基本功能,比如以智能方式重新使用takeWhile
来获得所需的结果。例如,您可以创建一个新的谓词列表,第一个元素为True
,takeWhile
此列表为真:
takeWhileP1 p xs = map snd (takeWhile fst (zip (True:map p xs) xs)
这也很好地概括了(在这种形式下不一定有效):
takeWhilePlusN n p xs = map snd (takeWhile fst (zip (replicate n True ++ map p xs) xs))
或者更容易阅读:
takeWhilePlusN n p xs =
let preds = replicate n True ++ map p xs
annotated = zip preds xs
in map snd (takeWhile fst annotated)
结果:
*Main> takeWhilePlusN 3 (<5) [1..10]
[1,2,3,4,5,6,7]
*Main> takeWhilePlusN 1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhileP1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhile (<5) [1..10]
[1,2,3,4]