Skip to content

Instantly share code, notes, and snippets.

@xukai92
Created November 24, 2020 11:09
Show Gist options
  • Save xukai92/0c8c9573c0aa176eca5f964559f281ec to your computer and use it in GitHub Desktop.
Save xukai92/0c8c9573c0aa176eca5f964559f281ec to your computer and use it in GitHub Desktop.
A variant of `takeuntil` from IterTools.jl
struct TakeUntil{I}
cond::Function
xs::I
end
"""
takeuntil(cond, xs)
An iterator that yields values from the iterator `xs` as long as the
predicate `cond` is true. Unlike `takewhile`, it also take the last
value for which the predicate `cond` is false.
'''jldoctest
julia> collect(takeuntil(x-> x^2 < 10, 1:100))
3-element Array{Int64,1}:
1
2
3
4
'''
"""
takeuntil(cond, xs) = TakeUntil(cond, xs)
function Base.iterate(it::TakeUntil, state=(false, nothing))
is_cond, state_xs = state
is_cond && return nothing
(val, state_xs) =
@ifsomething (state_xs === nothing ? iterate(it.xs) : iterate(it.xs, state_xs))
val, (it.cond(val), state_xs)
end
Base.IteratorSize(it::TakeUntil) = Base.SizeUnknown()
Base.eltype(::Type{TakeUntil{I}}) where {I} = eltype(I)
IteratorEltype(::Type{TakeUntil{I}}) where {I} = IteratorEltype(I)
@xukai92
Copy link
Author

xukai92 commented Nov 24, 2020

The current takewhile is convenient to use. But for cases in which I also want to take the last value which fails the condition, it cannot do what I want. Hence here is a function called takeuntil, which basically do something similar to takewhile but also include the value which first makes the function false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment