diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 94af6c5a25d51..531f83fa41fa6 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -343,6 +343,34 @@ function first(itr) x[1] end +""" + first(predicate, coll) + +Get the first element of `coll` satisfying `predicate` wrapped in `Some`. + +If no element of `coll` satisfies `predicate`, return `nothing`. + +# Examples +```jldoctest +julia> first(>(5), 1:10) +Some(6) + +julia> first(isodd, 2:2:10) |> isnothing +true + +julia> first(iseven, [5; 3; 4; 2; 6; 8]) |> something +4 + +julia> something(first(>(10), 1:10), 0) +0 +``` +""" +function first(predicate, itr) + for x in itr + predicate(x) && return Some(x) + end +end + """ first(itr, n::Integer) @@ -388,6 +416,43 @@ julia> last([1; 2; 3; 4]) """ last(a) = a[end] +""" + last(predicate, coll) + +Get the last element of `coll` satisfying `predicate` wrapped in `Some`. + +If no element of `coll` satisfies `predicate`, return `nothing`. + +# Examples +```jldoctest +julia> last(<(5), 1:10) +Some(4) + +julia> last(isodd, 2:2:10) |> isnothing +true + +julia> last(iseven, [5; 3; 4; 2; 6; 9]) |> something +6 + +julia> something(last(>(10), 1:10), 0) +0 +``` +""" +function last(predicate, itr) + out = nothing + for x in itr + out = ifelse(predicate(x), Some(x), out) + end + out +end + +# faster version for arrays +function last(predicate, a::AbstractArray) + @inbounds for i in reverse(eachindex(a)) + predicate(a[i]) && return Some(a[i]) + end +end + """ last(itr, n::Integer) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 2db1638c8c950..b2e3a30c0f723 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1141,3 +1141,13 @@ end @test last(itr, 1) == [itr[end]] @test_throws ArgumentError last(itr, -6) end + +@testset "first/last element satisfying predicate of $(typeof(itr))" for itr in (1:9, + collect(1:9), + reshape(1:9, (3, 3)), + ntuple(identity, 9)) + @test first(>(5), itr) |> something == 6 + @test last(<(5), itr) |> something == 4 + @test first(>(9), itr) == nothing + @test last(>(9), itr) == nothing +end