[英]Haskell takeWhile + 1
How can I write a takeWhile that would keep the first element that doesn't match the condition?我如何编写一个 takeWhile 来保留第一个不匹配条件的元素?
Example (obviously my example is trickier than this) :示例(显然我的示例比这更棘手):
Instead of takeWhile (\\× - > x! = 3) [1..10]
to return [1,2]
I need [1,2,3]
.而不是takeWhile (\\× - > x! = 3) [1..10]
返回[1,2]
我需要[1,2,3]
。
I thought of (takeWhile myFunc myList) ++ [find myFunc myList]
but it means I need to go through my list 2 times...我想到了(takeWhile myFunc myList) ++ [find myFunc myList]
但这意味着我需要遍历我的列表 2 次...
Any idea?任何的想法?
You can use span
or break
. 你可以使用span
或break
。
λ> span (/=3) [1..10]
([1,2],[3,4,5,6,7,8,9,10])
So you can do something like this: 所以你可以这样做:
takeWhileInc :: (a -> Bool) -> [a] -> [a]
takeWhileInc p xs = case zs of [] -> error "not found"
(z:_) -> ys ++ [z]
where
(ys, zs) = span p xs
(Or whatever you want to happen when zs
is empty because no 3
was found.) (或任何你希望发生的事情时, zs
,因为没有空3
被发现。)
You can roll your own. 你可以自己动手。
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p = foldr (\x ys -> if p x then x:ys else [x]) []
Compare it with 比较它
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p = foldr (\x ys -> if p x then x:ys else []) []
Explicit recursion would also be fine for this. 显式递归对此也没问题。
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p [] = []
takeWhileOneMore p (x:xs) =
if p x
then x : takeWhileOneMore p xs
else [x]
I like to use the base function more than many people do, such as re-using takeWhile
in an intelligent way to get the desired result. 我比许多人更喜欢使用基本功能,例如以智能方式重新使用takeWhile
来获得所需的结果。 For example, you can create a new list of predicates with the first element being True
and takeWhile
this list is true: 例如,您可以创建一个新的谓词列表,其中第一个元素为True
并且takeWhile
此列表为true:
takeWhileP1 p xs = map snd (takeWhile fst (zip (True:map p xs) xs)
This generalizes nicely as well (not necessarily efficient in this form): 这也很好地概括(在这种形式下不一定有效):
takeWhilePlusN n p xs = map snd (takeWhile fst (zip (replicate n True ++ map p xs) xs))
Or perhaps easier to read: 或者更容易阅读:
takeWhilePlusN n p xs =
let preds = replicate n True ++ map p xs
annotated = zip preds xs
in map snd (takeWhile fst annotated)
And the result: 结果如下:
*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]
When the condition fails for a element, instead of terminating with empty list, we can return the element.当某个元素的条件失败时,我们可以返回该元素,而不是以空列表终止。
takeWhileInclusive :: (a->Bool) -> [a] -> [a]
takeWhileInclusive _ [] = []
takeWhileInclusive predicate (x:xs) = if predicate x
then do (x: takeWhileInclusive predicate xs)
else [x]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.