Skip to content

Commit

Permalink
Added recursive merge function for NamedTuple, addresses #29215 (#29259)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsamaroo authored and JeffBezanson committed Nov 1, 2018
1 parent 6d416e4 commit 63f1c16
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
21 changes: 17 additions & 4 deletions base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,25 @@ end
end

"""
merge(a::NamedTuple, b::NamedTuple)
merge(a::NamedTuple, bs::NamedTuple...)
Construct a new named tuple by merging two existing ones.
The order of fields in `a` is preserved, but values are taken from matching
fields in `b`. Fields present only in `b` are appended at the end.
Construct a new named tuple by merging two or more existing ones, in a left-associative
manner. Merging proceeds left-to-right, between pairs of named tuples, and so the order of fields
present in both the leftmost and rightmost named tuples take the same position as they are found in the
leftmost named tuple. However, values are taken from matching fields in the rightmost named tuple that
contains that field. Fields present in only the rightmost named tuple of a pair are appended at the end.
A fallback is implemented for when only a single named tuple is supplied,
with signature `merge(a::NamedTuple)`.
```jldoctest
julia> merge((a=1, b=2, c=3), (b=4, d=5))
(a = 1, b = 4, c = 3, d = 5)
```
```jldoctest
julia> merge((a=1, b=2), (b=3, c=(d=1,)), (c=(d=2,),))
(a = 1, b = 3, c = (d = 2,))
```
"""
function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}
if @generated
Expand All @@ -241,6 +250,10 @@ merge(a::NamedTuple{()}, b::NamedTuple) = b

merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, b.data)

merge(a::NamedTuple, b::NamedTuple, cs::NamedTuple...) = merge(merge(a, b), cs...)

merge(a::NamedTuple) = a

"""
merge(a::NamedTuple, iterable)
Expand Down
5 changes: 5 additions & 0 deletions test/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,8 @@ y = map(v -> (a=v.a, b=v.a + v.b), [(a=1, b=missing), (a=1, b=2)])
# Iterator constructor
@test NamedTuple{(:a, :b), Tuple{Int, Float64}}(Any[1.0, 2]) === (a=1, b=2.0)
@test NamedTuple{(:a, :b)}(Any[1.0, 2]) === (a=1.0, b=2)

# Left-associative merge, issue #29215
@test merge((a=1, b=2), (b=3, c=4), (c=5,)) === (a=1, b=3, c=5)
@test merge((a=1, b=2), (b=3, c=(d=1,)), (c=(d=2,),)) === (a=1, b=3, c=(d=2,))
@test merge((a=1, b=2)) === (a=1, b=2)

0 comments on commit 63f1c16

Please sign in to comment.