Пух ... даже попытка правильно оформить заголовок уже доставляет мне головную боль.
У меня есть config.yml
с вложенными значениями, и я хотел бы определить функцию индексацииget_config()
, который принимает "подобные пути" строки значений.
«Объекты пути» строки значения соответствуют структуре вложенных объектов файла конфигурации. Основываясь на значении в виде пути, функция должна затем пойти и извлечь соответствующий объект иерархии («ветви» или «листья») из файла конфигурации.
Пример
Предположим, что этоСтруктура 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
]
Вот проанализированная версия, с которой вы можете поиграться:
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
]'
)
Доступ к объектам верхнего уровня легко с config::get(value)
:
config::get("column_names")
# $col_id
# [1] "id"
#
# $col_value
# [1] "value"
config::get("column_orders")
# [1] "hello" "world"
Но я также хотел бы получить доступ к более глубоким объектам, например, column_names: col_id
.
В псевдокоде:
config::get("column_names:col_id")
или
config::get("column_orders/data_structure_a")
Лучшее, что я мог придумать: полагаться на 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"
Хотя это и не элегантно, оно работает для большинства случаев использования, но не работает для неназванных объектов списка в файле конфигурации
get_config("column_orders:data_structure_a")
# <NA>
# NA
, поскольку мой подход к индексированию не очень хорошо сочетается с результатом unlist()
в неназванных списках:
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"
Таким образом, я бы хотел "пойти рекурсивно", но мой мозг говорит:"Ни за что, чувак"
Надлежащая проверка
Это решение близко (я полагаю).
Но я продолжаю думать, что мне нужно что-то вроде purrr::map2_if()
или purrr::pmap_if()
(которого AFAIK не существует) вместо purrr::map_if()
, поскольку мне нужно не только рекурсивно просматривать список, стоящий за config::get()
, но также выложена версия value
(например, через stringr::str_split(value, sep) %>% unlist() %>% as.list()
)?