Puh... even trying to frame the title properly already gives me a headache.
I have a config.yml
with nested values and I would like to define an indexing function get_config()
that accepts "path-like" value strings.
The "path entities" of the value string match the nested entity structure of the config file. Based on the path-like value the function should then go and grab the corresponding hierarchy entity (either "branches" or "leaves") from the config file.
Example
Suppose this is the structure of the config.yml
:
default:
column_names:
col_id: "id"
col_value: "value"
column_orders:
data_structure_a: [
column_names/col_id,
column_names/col_value
]
data_structure_b: [
column_names/col_value,
column_names/col_id
]
Here's a parsed version for you to play around with:
x <- yaml::yaml.load(
'default:
column_names:
col_id: "id"
col_value: "value"
column_orders:
data_structure_a: [
column_names/col_id,
column_names/col_value
]
data_structure_b: [
column_names/col_value,
column_names/col_id
]'
)
Accessing top-level entities is easy with config::get(value)
:
config::get("column_names")
# $col_id
# [1] "id"
#
# $col_value
# [1] "value"
config::get("column_orders")
# [1] "hello" "world"
But I would also like to access deeper entities, e.g. column_names: col_id
.
In pseudo code:
config::get("column_names:col_id")
or
config::get("column_orders/data_structure_a")
The best I could come up with so far: relying on unlist()
get_config <- function(value, sep = ":") {
if (value %>% stringr::str_detect(sep)) {
value <- value %>% stringr::str_replace(sep, ".")
configs <- config::get() %>% unlist()
configs[value]
} else {
config::get(value)
}
}
get_config("column_names")
# $col_id
# [1] "id"
#
# $col_value
# [1] "value"
get_config("column_names:col_id")
# column_names.col_id
# "id"
Though not elegant, it works for most use cases, but fails for unnamed list entities in the config file
get_config("column_orders:data_structure_a")
# <NA>
# NA
as my indexing approach doesn't play well with the result of unlist()
on unnamed lists:
config::get() %>% unlist()
# column_names.col_id column_names.col_value
# "id" "value"
# column_orders.data_structure_a1 column_orders.data_structure_a2
# "column_names/col_id" "column_names/col_value"
# column_orders.data_structure_b1 column_orders.data_structure_b2
# "column_names/col_value" "column_names/col_id"
Thus, I'd like to "go recursive" but my brain says: "no way, dude"
Due diligence
This solution comes close (I guess).
But I keep thinking that I need something like purrr::map2_if()
or purrr::pmap_if()
(which AFAIK don't exist) instead of purrr::map_if()
, as I need to not only traverse the list behind config::get()
recursively, but also a listified version of value
(e.g. via stringr::str_split(value, sep) %>% unlist() %>% as.list()
)?