在 Julia 中高效地将 Dict 转换为 NamedTuple

npr*_*npr 4 julia

我想要一个接受 aDict或 aNamedTuple作为输入的接口,但总是将输入转换为 a NamedTuple

给定一个 Dict

julia> dd = Dict(:a => 1, :b => 2)
Dict{Symbol,Int64} with 2 entries:
  :a => 1
  :b => 2
Run Code Online (Sandbox Code Playgroud)

我可以将其转换为NamedTuplewith

julia> (; dd...)
(a = 1, b = 2)
Run Code Online (Sandbox Code Playgroud)

但是,这两者都分配了令人惊讶的(对我而言)数量

julia> using BenchmarkTools

julia> @btime (; $dd...);
  1.033 ?s (12 allocations: 896 bytes)
Run Code Online (Sandbox Code Playgroud)

它不适用于嵌套Dicts,我想将其转换为嵌套NamedTuples

julia> dd_nested = Dict(:a => 1, :b => Dict(:x => 3, :y => 4))
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => Dict(:y=>4,:x=>3)

julia> (; dd_nested...)
(a = 1, b = Dict(:y => 4,:x => 3))
Run Code Online (Sandbox Code Playgroud)

其中所需的输出等于

julia> (a = 1, b = (x = 3, y = 4))
(a = 1, b = (x = 3, y = 4))
Run Code Online (Sandbox Code Playgroud)

Prz*_*fel 6

关于什么:

unzip(d::Dict) = (;(p.first => unzip(p.second) for p in d)...)
unzip(d) = d
Run Code Online (Sandbox Code Playgroud)

样品测试:

julia> unzip(dd)
(a = 1, b = (y = 4, x = 3))
Run Code Online (Sandbox Code Playgroud)

关于内存分配NamedTupleTools.jl,内存占用似乎略小。但是在任何一种情况下,您都在这里创建了相当多的数据结构,因此很可能您无法以更便宜的方式完成它。