How to make a named tuple from a dictionary?

Is there a simple way to make a named tuple from a Dict{Symbol, T}?

1 Like

There should be an easier way, but this works:

julia> NamedTuple{tuple(keys(di)...), Tuple{typeof.(collect(values(di)))...,}}((values(di)...,)) 
(a = 1, b = 5.6)```
2 Likes
dictkeys(d::Dict) = (collect(keys(d))...,)
dictvalues(d::Dict) = (collect(values(d))...,)

namedtuple(d::Dict{Symbol,T}) where {T} =
    NamedTuple{dictkeys(d)}(dictvalues(d))

dictionary = Dict(:a => 5, :b => 6, :c => 7)
Dict{Symbol,Int64} with 3 entries:
  :a => 5
  :b => 6
  :c => 7

namedtuple(dictionary)
(a = 5, b = 6, c = 7)

dictionary = Dict(:a => 5, :b => 6.0, :c => "7")
Dict{Symbol,Any} with 3 entries:
  :a => 5
  :b => 6.0
  :c => "7"

namedtuple(dictionary)
(a = 5, b = 6.0, c = "7")
1 Like

Thanks @mauro3 and @JeffreySarnoff for the replies, it would be nice of you to make a PR!

Is there nowadays a more convenient way to turn a dict into a named tuple?

julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol,Int64} with 2 entries:
  :a => 1                        
  :b => 2

julia> NamedTuple{Tuple(keys(d))}(values(d))
(a = 1, b = 2)
3 Likes

Probably touching internal detail, but…

((; kw...) -> kw.data)(; d...)

also works.

1 Like

AFAIU values(kw) is the public accessor for kw.data (to turn the keyword iterator into a NamedTuple).

2 Likes

Simply unpack the dict into a tuple.


(a = 1, dict...)


2 Likes

Tada:

julia> (; Dict(:a => 5, :b => 6, :c => 7)...)
(a = 5, b = 6, c = 7)

(Edit: note, that this already worked in Julia 0.7 when NamedTuples first appeared. Sometimes it just takes a bit longer to find the best solution…)

14 Likes

Ran into the inverse of this problem, so thought it might be helpful (at least not harmful) to post a solution for that here:

julia> nt = (a = 5, b = 6, c = 7)
(a = 5, b = 6, c = 7)

julia> Dict(pairs(nt))
Dict{Symbol,Int64} with 3 entries:
  :a => 5
  :b => 6
  :c => 7
1 Like

I think it would be nice if @mauro3’s solution were to appear explicitly in the documentation somewhere, and it might also be nice if there were some sort of namedtuple function, analogous to tuple which would probably make this functionality much easier to find.

1 Like

NamedTupleTools.jl exports namedtuple. I’d welcome issues that request additional features and be happier still with targeted PRs.

4 Likes

Ran into this again and just wanted to point out that the solution here seems incredibly slow

julia> @btime (;d...)
  967.857 ns (13 allocations: 928 bytes)
(a = 1, b = 2)

compare that to the inverse

julia> @btime Dict(pairs(nt))
  208.054 ns (7 allocations: 704 bytes)
Dict{Symbol,Int64} with 2 entries:
  :a => 1
  :b => 2

Anyone know of any way of speeding this up?

1 Like

@Tamas_Papp solution seems twice as fast than (; d...). But given that this is type-unstable code, it’s maybe not so suprising that it’s slow?