# Get value in nested data structure of arbitrary depth

Hi,

I would like to acess values of nested data structure with a `Tuple` representing the fields location in the data structure. The data structure can be of an arbitrary type and depth. Here is a MWE illustrating a few operations I would like to perform.

``````data = (a = 1, b = (a = [4,2], b = 3))
k1 = (:a,)
k2 = (:b, :a, 1)
function get_value(data, k)
# get value at key k
end
# returns 1
get_value(data, k1)
# returns 4
get_value(data, k2)
``````

Is there a way to achieve this? Is recursion the right approach?

Thanks!

A combination of dispatch and recursion would work:

``````get_value(data::NamedTuple, k::Symbol) = getproperty(data, k)
get_value(data::AbstractVector, k::Int) = getindex(data, k)
function get_value(data, k::Tuple)
if length(k) == 0
data
else
get_value(get_value(data, k[1]), k[2:end])
end
end
``````

Alternatively, you could just use a loop:

``````function get_value2(data, ks)
for k in ks
data = get(data, k, missing)  # get works for many types and handles missing keys
end
data
end
``````
2 Likes

Can you give some context? What is the application, and how is the tuple of fields being generated?

@bertschi, thank you. I think your second approach will work.

@stevengj, the context is a bit difficult to describe without going into a rabbit hole. Basically, I am trying to compare values in two data structures. I know the â€śkeysâ€ť of each, but not the values at those keys.

Itâ€™s not quite as bullet-proof as I had hoped for. A more rigorous solution might be using lenses from Accessors.jl:

``````julia> l1 = PropertyLens(:a)  # describes path into data, i.e., like k1 = (:a,)
(@o _.a)

julia> l1(data)
1

julia> l2 = Accessors.opticcompose(PropertyLens(:b), PropertyLens(:a), IndexLens(1))
(@o _.b.a[1])

julia> l2(data)
4
``````
1 Like

Thanks for the update! Accessors.jl looks like a relevant package.