From 6b4394ddd59122a807406a0b8294db863d1abe13 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 2 Mar 2019 14:31:07 -0800 Subject: [PATCH] Support filter for SkipMissing-wrapped arrays See discussion in issue 31188. --- NEWS.md | 1 + base/missing.jl | 31 +++++++++++++++++++++++++++++++ test/missing.jl | 9 +++++++++ 3 files changed, 41 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7b6beb3a10a6d..62893c84c2251 100644 --- a/NEWS.md +++ b/NEWS.md @@ -43,6 +43,7 @@ Standard library changes * `hasmethod` can now check for matching keyword argument names ([#30712]). * `startswith` and `endswith` now accept a `Regex` for the second argument ([#29790]). * `retry` supports arbitrary callable objects ([#30382]). +* `filter` now supports `SkipMissing`-wrapped arrays ([#31233]). * A no-argument construct to `Ptr{T}` has been added which constructs a null pointer ([#30919]) #### LinearAlgebra diff --git a/base/missing.jl b/base/missing.jl index f30b4e1a627c9..f9d1da1381f16 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -328,6 +328,37 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = end end +""" + filter(f, itr::SkipMissing{<:AbstractArray}) + +Return a 1-dimensional array similar to that wrapped by the given `SkipMissing` iterator +but with all missing elements and those for which `f` returns `false` removed. + +!!! compat "Julia 1.2" + This method requires Julia 1.2 or later. + +# Examples +```jldoctest +julia> x = [1 2; missing 4] +2×2 Array{Union{Missing, Int64},2}: + 1 2 + missing 4 + +julia> filter(isodd, skipmissing(x)) +1-element Array{Int64,1}: + 1 +``` +""" +function filter(f, itr::SkipMissing{<:AbstractArray}) + y = similar(itr.x, eltype(itr), 0) + for xi in itr.x + if xi !== missing && f(xi) + push!(y, xi) + end + end + y +end + """ coalesce(x, y...) diff --git a/test/missing.jl b/test/missing.jl index 81ad00c17612d..225b2af24e617 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -469,6 +469,15 @@ end @test_throws ArgumentError mapreduce(x -> x/2, +, itr) end end + + @testset "filter" begin + allmiss = Vector{Union{Int,Missing}}(missing, 10) + @test filter(isodd, allmiss) == Vector{Int}() + twod1 = [1.0f0 missing; 3.0f0 missing] + @test filter(x->x > 0, skipmissing(twod1)) == Float32[1.0f0, 3.0f0] + twod2 = [1.0f0 2.0f0; 3.0f0 4.0f0] + @test filter(x->x > 0, skipmissing(twod2)) == reshape(twod2, (4,)) + end end @testset "coalesce" begin