Во-первых, извиняюсь, что это длинный пост - он довольно подробный, и разница между результатом, которого я хотел бы достичь, и результатом, которого я смог достичь, неуловима, но значительна.
Основная проблема заключается в том, что я хочу создать рекурсивный список в R, в котором элементы списка увеличиваются вверх.
Основная причина в том, что сейчас я пытаюсь написать скрипт для автоматического создания переменной таблицы поиска в Google Tag Manager через GTM API.
Документация по созданию переменных находится здесь: https://developers.google.com/tag-manager/api/v2/reference/accounts/containers/workspaces/variables/create
Требуемый рабочий процесс такой:
- Извлечь таблицу сопоставления из Google Sheet с помощью пакета
googlesheets
- Преобразование соответствующих столбцов в формат списка
- Загрузка окончательной версии в GTM через GTM API
Проблема, с которой я сталкиваюсь в данный момент, - это шаг 2, создание списка правильным образом. Я нашел способ обратного инжиниринга списка, который предоставляет API GTM, но метод предполагает ручное добавление каждой строки из значений, которые должны отображаться в новый список, что не имеет смысла, когда у вас есть переменные длины строк (помимо того, что боль в заднице).
Вот так выглядит рабочий конечный результат (это было сделано ручным методом); это называется post_body1
:
$name
[1] "test1"
$type
[1] "smm"
$parameter
$parameter[[1]]
$parameter[[1]]$type
[1] "boolean"
$parameter[[1]]$key
[1] "setDefaultValue"
$parameter[[1]]$value
[1] "true"
$parameter[[2]]
$parameter[[2]]$type
[1] "template"
$parameter[[2]]$key
[1] "input"
$parameter[[2]]$value
[1] "{{Event Name}}"
$parameter[[3]]
$parameter[[3]]$type
[1] "list"
$parameter[[3]]$key
[1] "map"
$parameter[[3]]$list
$parameter[[3]]$list[[1]]
$parameter[[3]]$list[[1]]$type
[1] "map"
$parameter[[3]]$list[[1]]$map
$parameter[[3]]$list[[1]]$map[[1]]
$parameter[[3]]$list[[1]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[1]]$map[[1]]$value
[1] "explosion"
$parameter[[3]]$list[[1]]$map[[2]]
$parameter[[3]]$list[[1]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[1]]$map[[2]]$value
[1] "volcano"
$parameter[[3]]$list[[2]]
$parameter[[3]]$list[[2]]$type
[1] "map"
$parameter[[3]]$list[[2]]$map
$parameter[[3]]$list[[2]]$map[[1]]
$parameter[[3]]$list[[2]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[2]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[2]]$map[[1]]$value
[1] "flood"
$parameter[[3]]$list[[2]]$map[[2]]
$parameter[[3]]$list[[2]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[2]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[2]]$map[[2]]$value
[1] "tsunami"
$parameter[[3]]$list[[3]]
$parameter[[3]]$list[[3]]$type
[1] "map"
$parameter[[3]]$list[[3]]$map
$parameter[[3]]$list[[3]]$map[[1]]
$parameter[[3]]$list[[3]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[3]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[3]]$map[[1]]$value
[1] "drought"
$parameter[[3]]$list[[3]]$map[[2]]
$parameter[[3]]$list[[3]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[3]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[3]]$map[[2]]$value
[1] "heatwave"
Вот некоторые переменные:
variable_name <- 'test1'
map_values <- tibble(key=c('explosion','flood','drought'),
value = c('volcano','tsunami','heatwave'))
var_code <- 'smm'
set_default <- TRUE
map_input <- 'Event Name'
А вот код для создания списка выше - как уже упоминалось, это не масштабируемое решение.
post_body1 <- list(name = variable_name,
type = var_code,
parameter = list(
list(type = 'boolean',
key = 'setDefaultValue',
value = ifelse(set_default == TRUE,'true','false')),
list(type = 'template',
key = 'input',
value = paste('{{',map_input,'}}',sep='')),
list(type = 'list',
key = 'map',
list = list(list(
type = 'map',
map = list(list(
type = 'template',
key = 'key',
value = map_values$key[[1]]),
list(type = 'template',
key = 'value',
value = map_values$value[[1]])
)
),
list(type = 'map',
map = list(list(
type = 'template',
key = 'key',
value = map_values$key[[2]]),
list(type = 'template',
key = 'value',
value = map_values$value[[2]])
)
),
list(type = 'map',
map = list(list(
type = 'template',
key = 'key',
value = map_values$key[[3]]),
list(type = 'template',
key = 'value',
value = map_values$value[[3]])
)
)
)
)
)
)
Итак, я попытался создать новое решение, которое может обрабатывать создание post_body1$parameter[[3]]$list
программно, и я почти сделал это, но не совсем, а также я думаю, что это не очень элегантное решение, и есть вероятно, лучший способ создать его, используя пакет типа purrr
.
test_list <- list()
for (i in 1:nrow(map_values)) {
newlist <- list(
type = 'map',
map = list(list(
type = 'template',
key = 'key',
value = map_values$key[[i]]),
list(type = 'template',
key = 'value',
value = map_values$value[[i]])
)
)
test_list <- c(test_list,newlist)
}
post_body2 <- list(name = variable_name,
type = var_code,
parameter = list(
list(type = 'boolean',
key = 'setDefaultValue',
value = ifelse(set_default == TRUE,'true','false')),
list(type = 'template',
key = 'input',
value = paste('{{',map_input,'}}',sep='')),
list(type = 'list',
key = 'map',
list = list(test_list))
)
)
Таким образом, этот метод производит нечто, очень похожее на метод грубой силы выше, с одним существенным отличием: индекс для post_body2$parameter[[3]]$list
не увеличивается так же, как post_body1$parameter[[3]]$list
; вот как выглядит post_body2$parameter[[3]]$list
:
$parameter[[3]]$list
$parameter[[3]]$list[[1]]
$parameter[[3]]$list[[1]]$type
[1] "map"
$parameter[[3]]$list[[1]]$map
$parameter[[3]]$list[[1]]$map[[1]]
$parameter[[3]]$list[[1]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[1]]$map[[1]]$value
[1] "explosion"
$parameter[[3]]$list[[1]]$map[[2]]
$parameter[[3]]$list[[1]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[1]]$map[[2]]$value
[1] "volcano"
$parameter[[3]]$list[[1]]$type
[1] "map"
$parameter[[3]]$list[[1]]$map
$parameter[[3]]$list[[1]]$map[[1]]
$parameter[[3]]$list[[1]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[1]]$map[[1]]$value
[1] "flood"
$parameter[[3]]$list[[1]]$map[[2]]
$parameter[[3]]$list[[1]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[1]]$map[[2]]$value
[1] "tsunami"
$parameter[[3]]$list[[1]]$type
[1] "map"
$parameter[[3]]$list[[1]]$map
$parameter[[3]]$list[[1]]$map[[1]]
$parameter[[3]]$list[[1]]$map[[1]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[1]]$key
[1] "key"
$parameter[[3]]$list[[1]]$map[[1]]$value
[1] "drought"
$parameter[[3]]$list[[1]]$map[[2]]
$parameter[[3]]$list[[1]]$map[[2]]$type
[1] "template"
$parameter[[3]]$list[[1]]$map[[2]]$key
[1] "value"
$parameter[[3]]$list[[1]]$map[[2]]$value
[1] "heatwave"
Если вы все еще читаете, каким способом я могу создать этот список в нужном формате?
Редактировать: по запросу @ muddy-cloudskipper я добавляю dput
для желаемого результата, а именно:
list(name = "test1", type = "smm", parameter = list(list(type = "boolean",
key = "setDefaultValue", value = "true"), list(type = "template",
key = "input", value = "{{Event Name}}"), list(type = "list",
key = "map", list = list(list(type = "map", map = list(list(
type = "template", key = "key", value = "explosion"),
list(type = "template", key = "value", value = "volcano"))),
list(type = "map", map = list(list(type = "template",
key = "key", value = "flood"), list(type = "template",
key = "value", value = "tsunami"))), list(type = "map",
map = list(list(type = "template", key = "key", value = "drought"),
list(type = "template", key = "value", value = "heatwave")))))))
Я хочу создать функцию, которая приведет к этому выводу; было бы что-то вроде этого, хотя это не совсем правильно.
function (variable_name, var_code, set_default, map_input, map_values)
{
test_list <- list()
for (i in 1:nrow(map_values)) {
newlist <- list(type = "map", map = list(list(type = "template",
key = "key", value = map_values$key[[i]]), list(type = "template",
key = "value", value = map_values$value[[i]])))
test_list <- c(test_list, newlist)
}
post_body <- list(name = variable_name, type = var_code,
parameter = list(list(type = "boolean", key = "setDefaultValue",
value = ifelse(set_default == TRUE, "true", "false")),
list(type = "template", key = "input", value = paste("{{",
map_input, "}}", sep = "")), list(type = "list",
key = "map", list = list(test_list))))
return(post_body)
}