Accessing elements of a ComponentArray based on a variable

Warning: newbie here. Suppose I have something like

using ComponentArrays
p = ComponentArray()
p = ComponentArray(p; thing = 1)
tmp = ComponentArray{Int32}()
tmp = ComponentArray(tmp; a = 2)
tmp = ComponentArray(tmp; b = 3:4)
p = ComponentArray(p; other = tmp)

Is there a way to access p.other fields (or “top level” ones, for that matter) using something like str="b", then p.other.str?

I am thinking of the analogy in R, where I would, in a list, access entries by using p$other[[str]] as opposed to p$other$b if I know that I want to access b.

I have a lookup table from which I am getting the field I want to use. I could work in the other direction (iterate on the keys of p.other and go find the info in my lookup table), but there are instances where my lookup table has 10 entries while my p.other has millions (my guess is that the keys are well indexed and quickly searched, so finding a key is fast).

So and also out of curiosity, I was wondering if there’s a way to do the equivalent of my R statement.

I have so far worked out that I could find the index of b in the keys of p.other using findfirst, but for that, I need to figure out how to convert str to a symbol… That will be my next question if there is no way to directly do some direct equivalent of the R statement.

The easiest way to do this is to reuse the machinery that Julia uses under the hood. Whenever you do p.other, Julia rewrites this as getproperty(p, :other) (note that :other is a symbol).

So for what you want, you should be able to do

sym = :b
getproperty(p.other, sym)

or if you want to work with strings (this will be a bit more inefficient because of the extra conversion)

str = "b"
getproperty(p.other, Symbol(str))

Alternatively, if you are often iterating over various properties, a (potentially - I haven’t timed this) faster approach to use the label2index function in ComponentArrays and store the indices you need for direct use.

other_labels = ["a", "b"] 
other_indices = [label2index(p.other, label) for label in other_labels]
@show p.other[other_indices[2]] == p.other.b  # true

(Note rather than manually specifying all the labels, you can get all the labels using the labels function, but unfortunately it turns vectors into a list of their component scalars.)