From aed81fd876b942968ba234547aec6d4ecd791664 Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Wed, 24 Jul 2019 01:52:41 +0100 Subject: [PATCH 1/3] Support vectors as indices to NamedTuple Fix #32662, #27021 --- NEWS.md | 1 + base/namedtuple.jl | 2 ++ test/namedtuple.jl | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index f663bbc5c0ea7..d0d6bcf6ef340 100644 --- a/NEWS.md +++ b/NEWS.md @@ -33,6 +33,7 @@ New library functions * New `findall(pattern, string)` method where `pattern` is a string or regex ([#31834]). * `istaskfailed` is now documented and exported, like its siblings `istaskdone` and `istaskstarted` ([#32300]). * `RefArray` and `RefValue` objects now accept index `CartesianIndex()` in `getindex` and `setindex!` ([#32653]) +* `NamedTuple`s may now be subsetted with `getindex` ([#27021], [#32662]) Standard library changes ------------------------ diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 67eaaa9efe941..2a90466e72163 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -103,6 +103,8 @@ firstindex(t::NamedTuple) = 1 lastindex(t::NamedTuple) = nfields(t) getindex(t::NamedTuple, i::Int) = getfield(t, i) getindex(t::NamedTuple, i::Symbol) = getfield(t, i) +getindex(t::NamedTuple, v::AbstractVector{<:Integer}) = (; map(i->keys(t)[i] => t[i], v)...) +getindex(t::NamedTuple, v::AbstractVector{Symbol}) = (; map(i->i => t[i], v)...) indexed_iterate(t::NamedTuple, i::Int, state=1) = (getfield(t, i), i+1) isempty(::NamedTuple{()}) = true isempty(::NamedTuple) = false diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 82e711d625cbc..d9527fdd53ee1 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -21,6 +21,10 @@ @test (a=3,)[:a] == 3 @test (x=4, y=5, z=6).y == 5 @test (x=4, y=5, z=6).z == 6 +@test (x=4, y=5, z=6)[1:1] == (x=4,) +@test (x=4, y=5, z=6)[1:2] == (x=4, y=5) +@test (x=4, y=5, z=6)[[1,3]] == (x=4, z=6) +@test (x=4, y=5, z=6)[[:x,:y]] == (x=4, y=5) @test_throws ErrorException (x=4, y=5, z=6).a @test_throws BoundsError (a=2,)[0] @test_throws BoundsError (a=2,)[2] From 0a528e2c1fdc9dc940ac3e35771843118a4e2f0f Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Fri, 2 Aug 2019 22:55:11 +0100 Subject: [PATCH 2/3] Support Bool vectors for indexing NamedTuples Co-Authored-By: Matt Bauman --- base/namedtuple.jl | 5 +++++ test/namedtuple.jl | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 2a90466e72163..19978c813b92d 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -102,8 +102,13 @@ iterate(t::NamedTuple, iter=1) = iter > nfields(t) ? nothing : (getfield(t, iter firstindex(t::NamedTuple) = 1 lastindex(t::NamedTuple) = nfields(t) getindex(t::NamedTuple, i::Int) = getfield(t, i) +getindex(t::NamedTuple, i::Integer) = t[to_index(i)] getindex(t::NamedTuple, i::Symbol) = getfield(t, i) getindex(t::NamedTuple, v::AbstractVector{<:Integer}) = (; map(i->keys(t)[i] => t[i], v)...) +function getindex(t::NamedTuple, v::AbstractVector{Bool}) + length(t) == length(v) || throw(BoundsError(t, v)) + return t[to_index(v)] +end getindex(t::NamedTuple, v::AbstractVector{Symbol}) = (; map(i->i => t[i], v)...) indexed_iterate(t::NamedTuple, i::Int, state=1) = (getfield(t, i), i+1) isempty(::NamedTuple{()}) = true diff --git a/test/namedtuple.jl b/test/namedtuple.jl index d9527fdd53ee1..4bb9495e13ccb 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -25,6 +25,14 @@ @test (x=4, y=5, z=6)[1:2] == (x=4, y=5) @test (x=4, y=5, z=6)[[1,3]] == (x=4, z=6) @test (x=4, y=5, z=6)[[:x,:y]] == (x=4, y=5) +@test (x=4, y=5, z=6)[[true, true, false]] == (x=4, y=5) +@test (x=4, y=5, z=6)[[true, true, true]] == (x=4, y=5, z=6) +@test (x=4, y=5, z=6)[[false, false, false]] == NamedTuple() +@test (x=4, y=5, z=6)[Int[]] == NamedTuple() +@test_throws BoundsError (x=4, y=5, z=6)[[true, true]] +@test_throws ArgumentError (x=4, y=5, z=6)[true] +@test (x=4, y=5, z=6)[0x01] == (x=4, y=5, z=6)[Int16(1)] == 4 +@test (x=4, y=5, z=6)[0x01:0x01] == (x=4, y=5, z=6)[[Int16(1)]] == (x=4,) @test_throws ErrorException (x=4, y=5, z=6).a @test_throws BoundsError (a=2,)[0] @test_throws BoundsError (a=2,)[2] From 6945414bf4b0ad8e6f9f1ee641b42d9be6c916c7 Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Fri, 2 Aug 2019 23:22:41 +0100 Subject: [PATCH 3/3] Support [:x,1,2:z] as index to NamedTuple Co-Authored-By: Jameson Nash --- base/namedtuple.jl | 6 ++++-- test/namedtuple.jl | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 19978c813b92d..af253339217b1 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -104,12 +104,14 @@ lastindex(t::NamedTuple) = nfields(t) getindex(t::NamedTuple, i::Int) = getfield(t, i) getindex(t::NamedTuple, i::Integer) = t[to_index(i)] getindex(t::NamedTuple, i::Symbol) = getfield(t, i) -getindex(t::NamedTuple, v::AbstractVector{<:Integer}) = (; map(i->keys(t)[i] => t[i], v)...) function getindex(t::NamedTuple, v::AbstractVector{Bool}) length(t) == length(v) || throw(BoundsError(t, v)) return t[to_index(v)] end -getindex(t::NamedTuple, v::AbstractVector{Symbol}) = (; map(i->i => t[i], v)...) +getindex(t::NamedTuple, v::AbstractVector) = (; map(v) do i + k = i isa Symbol ? i : keys(t)[i] + return k => t[i] + end...) indexed_iterate(t::NamedTuple, i::Int, state=1) = (getfield(t, i), i+1) isempty(::NamedTuple{()}) = true isempty(::NamedTuple) = false diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 4bb9495e13ccb..b2bc200fb07bb 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -25,6 +25,7 @@ @test (x=4, y=5, z=6)[1:2] == (x=4, y=5) @test (x=4, y=5, z=6)[[1,3]] == (x=4, z=6) @test (x=4, y=5, z=6)[[:x,:y]] == (x=4, y=5) +@test (x=4, y=5, z=6)[[:x,2]] == (x=4, y=5) @test (x=4, y=5, z=6)[[true, true, false]] == (x=4, y=5) @test (x=4, y=5, z=6)[[true, true, true]] == (x=4, y=5, z=6) @test (x=4, y=5, z=6)[[false, false, false]] == NamedTuple()