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?

Thank you for your replies.

@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.