Skip to content

Commit d22ab50

Browse files
committed
add merge and structdiff for named tuples
1 parent 3c72902 commit d22ab50

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

base/namedtuple.jl

+41
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,44 @@ end
8989
namedtuple($NT, $(args...))
9090
end
9191
end
92+
93+
# a version of `in` for the older world these generated functions run in
94+
function sym_in(x, itr)
95+
for y in itr
96+
y === x && return true
97+
end
98+
return false
99+
end
100+
101+
@generated function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}
102+
names = Symbol[an...]
103+
for n in bn
104+
if !sym_in(n, an)
105+
push!(names, n)
106+
end
107+
end
108+
vals = map(names) do n
109+
if sym_in(n, bn)
110+
:(getfield(b, $(Expr(:quote, n))))
111+
else
112+
:(getfield(a, $(Expr(:quote, n))))
113+
end
114+
end
115+
names = (names...,)
116+
:(namedtuple(NamedTuple{$names}, $(vals...)))
117+
end
118+
119+
@generated function structdiff(a::NamedTuple{an},
120+
b::Union{NamedTuple{bn},Type{NamedTuple{bn}}}) where {an,bn}
121+
names = Symbol[]
122+
for n in an
123+
if !sym_in(n, bn)
124+
push!(names, n)
125+
end
126+
end
127+
vals = map(names) do n
128+
:(getfield(a, $(Expr(:quote, n))))
129+
end
130+
names = (names...,)
131+
:(namedtuple(NamedTuple{$names}, $(vals...)))
132+
end

test/namedtuple.jl

+10
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,13 @@
5151
@test map(+, (x=1, y=2), (x=10, y=20)) == (x=11, y=22)
5252
@test map(string, (x=1, y=2)) == (x="1", y="2")
5353
@test map(round, (x=1//3, y=Int), (x=3, y=2//3)) == (x=0.333, y=1)
54+
55+
@test merge((a=1, b=2), (a=10,)) == (a=10, b=2)
56+
@test merge((a=1, b=2), (a=10, z=20)) == (a=10, b=2, z=20)
57+
@test merge((a=1, b=2), (z=20,)) == (a=1, b=2, z=20)
58+
59+
@test Base.structdiff((a=1, b=2), (b=3,)) == (a=1,)
60+
@test Base.structdiff((a=1, b=2, z=20), (b=3,)) == (a=1, z=20)
61+
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1)) == (a=1,)
62+
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1, a=0)) == NamedTuple()
63+
@test Base.structdiff((a=1, b=2, z=20), NamedTuple{(:b,)}) == (a=1, z=20)

0 commit comments

Comments
 (0)