# Check equality of two NamedTuples with order of the fields ignored

Suppose I have the following two instances of `NamedTuple`.

``````julia> a = (x=1, y=2)
(x = 1, y = 2)

julia> b = (y=2, x=1)
(y = 2, x = 1)

julia> a == b
false
``````

What would be the best approach to test whether `a` and `b` contain the same key-value pairs while ignoring the order of the pairs? (So, I want something that returns `true` for comparing `a` and `b`.)

Thanks!

``````julia> a = (x=1, y=2)
(x = 1, y = 2)

julia> b = (y=2, x=1)
(y = 2, x = 1)

julia> ntd(t) = Dict(zip(keys(t), values(t)))
ntd (generic function with 1 method)

julia> ntd(a) == ntd(b)
true
``````
1 Like
``````sortednames(nt::NamedTuple{N,T}) where {N,T} =
Tuple(sort([N...]))

sortednt(nt::NamedTuple) =
NamedTuple{sortednames(nt)}(nt)

sortednt(a) == sortednt(b)
``````
3 Likes
``````julia> all(k->getfield(a,k) == getfield(b,k), keys(a))
true
``````
1 Like

works nicely where

``````length(a) == length(allnames(a,b))
# and
allnames(a,b) =
Tuple(union(fieldnames(typeof(a)), fieldnames(typeof(b))))
``````
``````≊(x::NamedTuple{N,T}, y::NamedTuple{N2,T2}) where {N,T,N2,T2} =
length(N) === length(union(N,N2)) &&
all(k->getfield(x,k) == getfield(y,k), keys(x))

a = (x=1, y=2)
b = (y=2, x=1)

a ≊ b # true
``````
4 Likes

Those solution do not seem to handle recursive namedtuple, eg.

``````aa = (qux = (quuux = 4, quux = 3), foo = (bar = 1, baz = 2))
bb = (foo = (bar = 1, baz = 2), qux = (quuux = 4, quux = 3))
``````

This is more of a bug in Base IMO. (may need a `@pure sort(::Tuple)` to dispatch statically)