From b286f17b0b99935a199a60b432d77b7525f23914 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 7 Jan 2018 16:43:42 +0100 Subject: [PATCH] Also return indices from keys() for AbstractString, Tuple and NamedTuple, and add tests --- NEWS.md | 10 +++++----- base/array.jl | 7 ++++--- test/arrayops.jl | 4 ---- test/dict.jl | 7 +++++++ test/namedtuple.jl | 5 +++++ test/strings/search.jl | 4 ++++ test/tuple.jl | 7 +++++++ 7 files changed, 32 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6947bc7585de5..8d89adafe9858 100644 --- a/NEWS.md +++ b/NEWS.md @@ -365,11 +365,11 @@ This section lists changes that do not have deprecation warnings. * `findn(x::AbstractVector)` now returns a 1-tuple with the vector of indices, to be consistent with higher order arrays ([#25365]). - * `find` now returns the same type of indices as `keys`/`pairs` for `AbstractArray` and - `AbstractDict` objects ([#24774]). In particular, this means that it returns - `CartesianIndex` objects for matrices and higher-dimensional arrays instead of - always returning linear indices as it was previously the case. Use - `Int[LinearIndices(size(a))[i] for i in find(f, a)]` to compute linear indices + * `find` now returns the same type of indices as `keys`/`pairs` for `AbstractArray`, + `AbstractDict`, `AbstractString`, `Tuple` and `NamedTuple` objects ([#24774]). + In particular, this means that it returns `CartesianIndex` objects for matrices + and higher-dimensional arrays instead of linear indices as it was previously the case. + Use `Int[LinearIndices(size(a))[i] for i in find(f, a)]` to compute linear indices. Library improvements -------------------- diff --git a/base/array.jl b/base/array.jl index 3b99bf874bd8a..bd98f14828a7b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1724,8 +1724,9 @@ Return a vector `I` of the indices or keys of `A` where `f(A[I])` returns `true` If there are no such elements of `A`, return an empty array. Indices or keys are of the same type as those returned by [`keys(A)`](@ref) -and [`pairs(A)`](@ref) for `AbstractArray` and `Associative` objects, -and are linear indices of type `Int` for other iterables. +and [`pairs(A)`](@ref) for `AbstractArray`, `AbstractDict`, `AbstractString` +`Tuple` and `NamedTuple` objects, and are linear indices starting at `1` +for other iterables. # Examples ```jldoctest @@ -1771,7 +1772,7 @@ julia> find(x -> x >= 0, d) """ find(testf::Function, A) = collect(first(p) for p in _pairs(A) if testf(last(p))) -_pairs(A::Union{AbstractArray, AbstractDict}) = pairs(A) +_pairs(A::Union{AbstractArray, AbstractDict, AbstractString, Tuple, NamedTuple}) = pairs(A) _pairs(iter) = zip(OneTo(typemax(Int)), iter) # safe for objects that don't implement length """ diff --git a/test/arrayops.jl b/test/arrayops.jl index 967a3d423f2b5..2a4791701f0dd 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -471,10 +471,6 @@ end @test find(!iszero, A) == [CartesianIndex(1, 1), CartesianIndex(2, 1), CartesianIndex(1, 2), CartesianIndex(2, 2)] end -@testset "find with Dict" begin - d = Dict(:A => 10, :B => -1, :C => 0) - @test sort(find(x -> x >= 0, d)) == [:A, :C] -end @testset "find with general iterables" begin s = "julia" @test find(c -> c == 'l', s) == [3] diff --git a/test/dict.jl b/test/dict.jl index d3df55dab77a1..b13fee04f2c8c 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -757,3 +757,10 @@ end end @test map(string, keys(d)) == Set(["1","3"]) end + +@testset "find" begin + @test @inferred find(equalto(1), Dict(:a=>1, :b=>2)) == [:a] + @test @inferred sort(find(equalto(1), Dict(:a=>1, :b=>1))) == [:a, :b] + @test @inferred isempty(find(equalto(1), Dict())) + @test @inferred isempty(find(equalto(1), Dict(:a=>2, :b=>3))) +end \ No newline at end of file diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 5b2c2179a05a5..df5e5d274e3f3 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -208,3 +208,8 @@ abstr_nt_22194_3() @test Base.structdiff((a=1, b=2, z=20), NamedTuple{(:b,)}) == (a=1, z=20) @test typeof(Base.structdiff(NamedTuple{(:a, :b), Tuple{Int32, Union{Int32, Nothing}}}((1, Int32(2))), (a=0,))) === NamedTuple{(:b,), Tuple{Union{Int32, Nothing}}} + +@test @inferred find(equalto(1), (a=1, b=2)) == [:a] +@test @inferred find(equalto(1), (a=1, b=1)) == [:a, :b] +@test @inferred isempty(find(equalto(1), NamedTuple())) +@test @inferred isempty(find(equalto(1), (a=2, b=3))) \ No newline at end of file diff --git a/test/strings/search.jl b/test/strings/search.jl index 8d499207589eb..73f08000b898f 100644 --- a/test/strings/search.jl +++ b/test/strings/search.jl @@ -324,3 +324,7 @@ end @test findnext(equalto('('), "(⨳(", 2) == 5 @test findlast(equalto('('), "(⨳(") == 5 @test findprev(equalto('('), "(⨳(", 2) == 1 + +@test @inferred find(equalto('a'), "éa") == [3] +@test @inferred find(equalto('€'), "€€") == [1, 4] +@test @inferred isempty(find(equalto('é'), "")) \ No newline at end of file diff --git a/test/tuple.jl b/test/tuple.jl index 74becec9e6401..f7f5d0260da31 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -364,3 +364,10 @@ end @testset "issue 24707" begin @test eltype(Tuple{Vararg{T}} where T<:Integer) >: Integer end + +@testset "find" begin + @test @inferred find(equalto(1), (1, 2)) == [1] + @test @inferred find(equalto(1), (1, 1)) == [1, 2] + @test @inferred isempty(find(equalto(1), ())) + @test @inferred isempty(find(equalto(1), (2, 3))) +end \ No newline at end of file