From e4a3a063181c12120b7e3d818ac014ee7a407500 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 16 Dec 2017 18:44:02 +0100 Subject: [PATCH] Deprecate findin(a, b) in favor of find(occursin(b), a) --- NEWS.md | 2 ++ base/abstractarray.jl | 4 +-- base/array.jl | 47 ++++++++--------------------------- base/deprecated.jl | 2 ++ base/exports.jl | 1 - base/range.jl | 14 ++--------- base/sparse/sparsematrix.jl | 2 ++ base/sparse/sparsevector.jl | 2 ++ doc/src/stdlib/collections.md | 1 - stdlib/Dates/test/ranges.jl | 22 ++++++++-------- test/arrayops.jl | 28 ++++++++++----------- test/ranges.jl | 21 ++++++---------- 12 files changed, 56 insertions(+), 90 deletions(-) diff --git a/NEWS.md b/NEWS.md index c82ccaa797396d..495ca04f79dd2a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -903,6 +903,8 @@ Deprecated or removed * `ismatch(regex, str)` has been deprecated in favor of `contains(str, regex)` ([#24673]). + * `findin(a, b)` has been deprecated in favor of `find(occursin(b), a)` ([#24673]). + Command-line option changes --------------------------- diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 08fb1be991a346..8f0da6209b6285 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1055,7 +1055,7 @@ get(A::AbstractArray, I::Dims, default) = checkbounds(Bool, A, I...) ? A[I...] : function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{AbstractRange,AbstractVector{Int}}, default::T) where T # 1d is not linear indexing - ind = findin(I, indices1(A)) + ind = find(occursin(indices1(A)), I) X[ind] = A[I[ind]] Xind = indices1(X) X[first(Xind):first(ind)-1] = default @@ -1064,7 +1064,7 @@ function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{AbstractRange,Ab end function get!(X::AbstractArray{T}, A::AbstractArray, I::Union{AbstractRange,AbstractVector{Int}}, default::T) where T # Linear indexing - ind = findin(I, 1:length(A)) + ind = find(occursin(1:length(A)), I) X[ind] = A[I[ind]] X[1:first(ind)-1] = default X[last(ind)+1:length(X)] = default diff --git a/base/array.jl b/base/array.jl index 5a54e3de6eca65..2738382b372bfd 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1799,6 +1799,7 @@ end find(x::Bool) = x ? [1] : Vector{Int}() find(testf::Function, x::Number) = !testf(x) ? Vector{Int}() : [1] +find(p::OccursIn, x::Number) = x in p.x ? Vector{Int}() : [1] findn(A::AbstractVector) = find(A) @@ -2052,7 +2053,7 @@ function _findin(a, b) ind end -# If two collections are already sorted, findin can be computed with +# If two collections are already sorted, _findin can be computed with # a single traversal of the two collections. This is much faster than # using a hash table (although it has the same complexity). function _sortedfindin(v, w) @@ -2094,42 +2095,16 @@ function _sortedfindin(v, w) return out end -""" - findin(a, b) - -Return the indices of elements in collection `a` that appear in collection `b`. - -# Examples -```jldoctest -julia> a = collect(1:3:15) -5-element Array{Int64,1}: - 1 - 4 - 7 - 10 - 13 - -julia> b = collect(2:4:10) -3-element Array{Int64,1}: - 2 - 6 - 10 - -julia> findin(a,b) # 10 is the only common element -1-element Array{Int64,1}: - 4 -``` -""" -function findin(a::Array{<:Real}, b::Union{Array{<:Real},Real}) - if issorted(a, Sort.Forward) && issorted(b, Sort.Forward) - return _sortedfindin(a, b) +function find(pred::OccursIn{<:Union{Array{<:Real},Real}}, x::Array{<:Real}) + if issorted(x, Sort.Forward) && issorted(pred.x, Sort.Forward) + return _sortedfindin(x, pred.x) else - return _findin(a, b) + return _findin(x, pred.x) end end # issorted fails for some element types so the method above has to be restricted # to element with isless/< defined. -findin(a, b) = _findin(a, b) +find(pred::OccursIn, x::Union{AbstractArray, Tuple}) = _findin(x, pred.x) # Copying subregions function indcopy(sz::Dims, I::Vector) @@ -2138,8 +2113,8 @@ function indcopy(sz::Dims, I::Vector) for i = n+1:length(sz) s *= sz[i] end - dst = eltype(I)[findin(I[i], i < n ? (1:sz[i]) : (1:s)) for i = 1:n] - src = eltype(I)[I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n] + dst = eltype(I)[_findin(I[i], i < n ? (1:sz[i]) : (1:s)) for i = 1:n] + src = eltype(I)[I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n] dst, src end @@ -2149,8 +2124,8 @@ function indcopy(sz::Dims, I::Tuple{Vararg{RangeIndex}}) for i = n+1:length(sz) s *= sz[i] end - dst::typeof(I) = ntuple(i-> findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I) - src::typeof(I) = ntuple(i-> I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I) + dst::typeof(I) = ntuple(i-> _findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I) + src::typeof(I) = ntuple(i-> I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I) dst, src end diff --git a/base/deprecated.jl b/base/deprecated.jl index 26138fbe95f47e..a5e8b784e58ef6 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -3856,6 +3856,8 @@ end @deprecate ismatch(r::Regex, s::AbstractString) contains(s, r) +@deprecate findin(a, b) find(occursin(b), a) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/exports.jl b/base/exports.jl index 2b256e30979e02..701e97050710e2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -494,7 +494,6 @@ export find, findfirst, findlast, - findin, findmax, findmin, findmin!, diff --git a/base/range.jl b/base/range.jl index b46bad0ac07ee5..2219e560338530 100644 --- a/base/range.jl +++ b/base/range.jl @@ -705,7 +705,7 @@ function intersect(r1::AbstractRange, r2::AbstractRange, r3::AbstractRange, r::A i end -# findin (the index of intersection) +# _findin (the index of intersection) function _findin(r::AbstractRange{<:Integer}, span::AbstractUnitRange{<:Integer}) local ifirst local ilast @@ -724,17 +724,7 @@ function _findin(r::AbstractRange{<:Integer}, span::AbstractUnitRange{<:Integer} ifirst = fr >= fspan ? 1 : length(r)+1 ilast = fr <= lspan ? length(r) : 0 end - ifirst, ilast -end - -function findin(r::AbstractUnitRange{<:Integer}, span::AbstractUnitRange{<:Integer}) - ifirst, ilast = _findin(r, span) - ifirst:ilast -end - -function findin(r::AbstractRange{<:Integer}, span::AbstractUnitRange{<:Integer}) - ifirst, ilast = _findin(r, span) - ifirst:1:ilast + r isa AbstractUnitRange ? (ifirst:ilast) : (ifirst:1:ilast) end ## linear operations on ranges ## diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index b864016b94f114..1d2516c01c133d 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1276,6 +1276,8 @@ function find(p::Function, S::SparseMatrixCSC) I, J = _findn(p, S) return Base._sub2ind(sz, I, J) end +find(p::Base.OccursIn, x::SparseMatrixCSC) = + invoke(find, Tuple{Base.OccursIn, AbstractArray}, p, x) findn(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = _findn(x->true, S) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 4ee09d93a8080e..4d86349377166e 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -705,6 +705,8 @@ function find(p::Function, x::SparseVector{<:Any,Ti}) where Ti return I end +find(p::Base.OccursIn, x::SparseVector{<:Any,Ti}) where {Ti} = + invoke(find, Tuple{Base.OccursIn, AbstractArray}, p, x) function findnz(x::SparseVector{Tv,Ti}) where {Tv,Ti} numnz = nnz(x) diff --git a/doc/src/stdlib/collections.md b/doc/src/stdlib/collections.md index 5fccee695aa1af..6c9c33d3a5236d 100644 --- a/doc/src/stdlib/collections.md +++ b/doc/src/stdlib/collections.md @@ -77,7 +77,6 @@ Fully implemented by: Base.in Base.eltype Base.indexin -Base.findin Base.unique Base.unique! Base.allunique diff --git a/stdlib/Dates/test/ranges.jl b/stdlib/Dates/test/ranges.jl index 7e9c51cdc07222..2b8d4e03acc844 100644 --- a/stdlib/Dates/test/ranges.jl +++ b/stdlib/Dates/test/ranges.jl @@ -26,7 +26,7 @@ let @test_throws ArgumentError minimum(dr) @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] - @test findin(dr, dr) == Int64[] + @test find(occursin(dr), dr) == Int64[] @test [dr;] == T[] @test isempty(reverse(dr)) @test length(reverse(dr)) == 0 @@ -58,7 +58,7 @@ let if len < 10000 dr1 = [i for i in dr] @test length(dr1) == len - @test findin(dr, dr) == [1:len;] + @test find(occursin(dr), dr) == [1:len;] @test length([dr;]) == len @test dr == dr1 @test hash(dr) == hash(dr1) @@ -84,7 +84,7 @@ let @test_throws ArgumentError minimum(dr) @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] - @test findin(dr, dr) == Int64[] + @test find(occursin(dr), dr) == Int64[] @test [dr;] == T[] @test isempty(reverse(dr)) @test length(reverse(dr)) == 0 @@ -116,7 +116,7 @@ let if len < 10000 dr1 = [i for i in dr] @test length(dr1) == len - @test findin(dr, dr) == [1:len;] + @test find(occursin(dr), dr) == [1:len;] @test length([dr;]) == len @test dr == dr1 @test hash(dr) == hash(dr1) @@ -144,7 +144,7 @@ let @test_throws ArgumentError minimum(dr) @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] - @test findin(dr, dr) == Int64[] + @test find(occursin(dr), dr) == Int64[] @test [dr;] == T[] @test isempty(reverse(dr)) @test length(reverse(dr)) == 0 @@ -176,7 +176,7 @@ let if len < 10000 dr1 = [i for i in dr] @test length(dr1) == len - @test findin(dr, dr) == [1:len;] + @test find(occursin(dr), dr) == [1:len;] @test length([dr;]) == len @test dr == dr1 @test hash(dr) == hash(dr1) @@ -202,7 +202,7 @@ let @test_throws ArgumentError minimum(dr) @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] - @test findin(dr, dr) == Int64[] + @test find(occursin(dr), dr) == Int64[] @test [dr;] == T[] @test isempty(reverse(dr)) @test length(reverse(dr)) == 0 @@ -234,7 +234,7 @@ let if len < 10000 dr1 = [i for i in dr] @test length(dr1) == len - @test findin(dr, dr) == [1:len;] + @test find(occursin(dr), dr) == [1:len;] @test length([dr;]) == len @test dr == dr1 @test hash(dr) == hash(dr1) @@ -293,7 +293,7 @@ drs2 = map(x->Dates.Date(first(x)):step(x):Dates.Date(last(x)), drs) @test map(length, drs) == map(x->size(x)[1], drs) @test map(length, drs) == map(x->length(Dates.Date(first(x)):step(x):Dates.Date(last(x))), drs) @test map(length, drs) == map(x->length(reverse(x)), drs) -@test all(x->findin(x, x)==[1:length(x);], drs[1:4]) +@test all(x->find(occursin(x), x)==[1:length(x);], drs[1:4]) @test isempty(dr2) @test all(x->reverse(x) == range(last(x), -step(x), length(x)), drs) @test all(x->minimum(x) == (step(x) < zero(step(x)) ? last(x) : first(x)), drs[4:end]) @@ -371,7 +371,7 @@ drs = Any[dr, dr1, dr2, dr3, dr4, dr5, dr6, dr7, dr8, dr9, dr10, dr11, dr12, dr13, dr14, dr15, dr16, dr17, dr18, dr19, dr20] @test map(length, drs) == map(x->size(x)[1], drs) -@test all(x->findin(x, x) == [1:length(x);], drs[1:4]) +@test all(x->find(occursin(x), x) == [1:length(x);], drs[1:4]) @test isempty(dr2) @test all(x->reverse(x) == last(x): - step(x):first(x), drs) @test all(x->minimum(x) == (step(x) < zero(step(x)) ? last(x) : first(x)), drs[4:end]) @@ -557,7 +557,7 @@ drs = Any[dr, dr1, dr2, dr3, dr8, dr9, dr10, dr11, dr12, dr13, dr14, dr15, dr16, dr17, dr18, dr19, dr20] @test map(length, drs) == map(x->size(x)[1], drs) -@test all(x->findin(x, x) == [1:length(x);], drs[1:4]) +@test all(x->find(occursin(x), x) == [1:length(x);], drs[1:4]) @test isempty(dr2) @test all(x->reverse(x) == last(x): - step(x):first(x), drs) @test all(x->minimum(x) == (step(x) < zero(step(x)) ? last(x) : first(x)), drs[4:end]) diff --git a/test/arrayops.jl b/test/arrayops.jl index adc3128c4fef1a..fcb7a11693d94b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -265,30 +265,30 @@ end a = [3, 5, -7, 6] b = [4, 6, 2, -7, 1] - ind = findin(a, b) + ind = find(occursin(b), a) @test ind == [3,4] - @test findin(a, Int[]) == Int[] - @test findin(Int[], a) == Int[] + @test find(occursin(Int[]), a) == Int[] + @test find(occursin(a), Int[]) == Int[] a = [1,2,3,4,5] b = [2,3,4,6] - @test findin(a, b) == [2,3,4] - @test findin(b, a) == [1,2,3] - @test findin(a, Int[]) == Int[] - @test findin(Int[], a) == Int[] + @test find(occursin(b), a) == [2,3,4] + @test find(occursin(a), b) == [1,2,3] + @test find(occursin(Int[]), a) == Int[] + @test find(occursin(a), Int[]) == Int[] a = collect(1:3:15) b = collect(2:4:10) - @test findin(a, b) == [4] - @test findin([a[1:4]; a[4:end]], b) == [4,5] + @test find(occursin(b), a) == [4] + @test find(occursin(b), [a[1:4]; a[4:end]]) == [4,5] - @test findin([1.0, NaN, 2.0], NaN) == [2] - @test findin([1.0, 2.0, NaN], NaN) == [3] + @test find(occursin(NaN), [1.0, NaN, 2.0]) == [2] + @test find(occursin(NaN), [1.0, 2.0, NaN]) == [3] - @testset "findin for uncomparable element types" begin + @testset "find(::OccursIn, b) for uncomparable element types" begin a = [1 + 1im, 1 - 1im] - @test findin(a, 1 + 1im) == [1] - @test findin(a, a) == [1,2] + @test find(occursin(1 + 1im), a) == [1] + @test find(occursin(a), a) == [1,2] end rt = Base.return_types(setindex!, Tuple{Array{Int32, 3}, UInt8, Vector{Int}, Int16, UnitRange{Int}}) diff --git a/test/ranges.jl b/test/ranges.jl index bb93377e35c489..2eaf006018891f 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -249,21 +249,15 @@ end @test length(0.0:-0.5) == 0 @test length(1:2:0) == 0 end - @testset "findin" begin - @test findin([5.2, 3.3], 3:20) == findin([5.2, 3.3], collect(3:20)) + @testset "find(::OccursIn, ::Array)" begin + @test find(occursin(3:20), [5.2, 3.3]) == find(occursin(collect(3:20)), [5.2, 3.3]) let span = 5:20, r = -7:3:42 - @test findin(r, span) == 5:10 + @test find(occursin(span), r) == 5:10 r = 15:-2:-38 - @test findin(r, span) == 1:6 + @test find(occursin(span), r) == 1:6 end - #@test isempty(findin(5+0*(1:6), 2:4)) - #@test findin(5+0*(1:6), 2:5) == 1:6 - #@test findin(5+0*(1:6), 2:7) == 1:6 - #@test findin(5+0*(1:6), 5:7) == 1:6 - #@test isempty(findin(5+0*(1:6), 6:7)) - #@test findin(5+0*(1:6), 5:5) == 1:6 end @testset "reverse" begin @test reverse(reverse(1:10)) == 1:10 @@ -1115,15 +1109,16 @@ end @test intersect(r, Base.OneTo(2)) == Base.OneTo(2) @test intersect(r, 0:5) == 1:3 @test intersect(r, 2) === intersect(2, r) === 2:2 - @test findin(r, r) === findin(r, 1:length(r)) === findin(1:length(r), r) === 1:length(r) + @test find(occursin(r), r) === find(occursin(1:length(r)), r) === + find(occursin(r), 1:length(r)) === 1:length(r) io = IOBuffer() show(io, r) str = String(take!(io)) @test str == "Base.OneTo(3)" end let r = Base.OneTo(7) - @test findin(r, 2:(length(r) - 1)) === 2:(length(r) - 1) - @test findin(2:(length(r) - 1), r) === 1:(length(r) - 2) + @test find(occursin(2:(length(r) - 1)), r) === 2:(length(r) - 1) + @test find(occursin(r), 2:(length(r) - 1)) === 1:(length(r) - 2) end end