在R中使用规则递增索引创建递归列表

时间:2019-01-24 14:15:27

标签: r google-api google-tag-manager purrr

首先,很抱歉,这是一篇很长的文章-内容很详尽,我想要实现的结果与我已经能够实现的结果之间的差异是微妙而重要的。

核心问题是我想在R中创建一个递归列表,其中列表元素向上递增。

核心原因是,现在我正尝试编写脚本以通过GTM API在Google跟踪代码管理器中自动创建查找表变量。

用于创建变量的文档在这里:https://developers.google.com/tag-manager/api/v2/reference/accounts/containers/workspaces/variables/create

所需的工作流程是这样:

  1. 使用googlesheets包从Google表格中提取映射表
  2. 将相关列转换为列表格式
  3. 通过GTM API将最终版本上传到GTM

我目前遇到的问题是步骤2,以正确的方式创建列表。我想出了一种对GTM API提供的列表进行反向工程的方法,但是该方法涉及手动将值中的每一行添加到要映射为新列表的位置,当行长可变时(除了屁股疼痛)。

这是工作最终结果的外观(这是通过手动方法完成的);这称为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)
}

1 个答案:

答案 0 :(得分:1)

我认为这应该起作用,我分别构建列表的可变部分,然后将所有内容粘在一起:

  sublist <- unname(Map(function(key,value) list(type = "map",
                                                 map=list(
    list(type="template",
         key ="key",
         value = key),
    list(type = "template",
         key = "value",
         value = value))), map_values$key, map_values$value))

  res <- list(name = variable_name,
              type = var_code,
              parameter = c(list(
                list(type = 'boolean',
                     key = 'setDefaultValue',
                     value = ifelse(set_default == TRUE,'true','false')),
                list(type = 'template',
                     key = 'input',
                     value = paste('{{',map_input,'}}',sep=''))),
                list(list(type = "list",
                     key = "map",
                     list=sublist))))

  identical(res,output)
  # [1] TRUE