【问题标题】:Access named nested list elements with string name in R在R中使用字符串名称访问命名嵌套列表元素
【发布时间】:2020-01-13 20:32:29
【问题描述】:

我试图找到一种通过将名称作为字符串(或字符串列表)传递来访问命名嵌套列表元素的方法。你可以用attr(the_thing, "the_attr") 做一些事情,但我想做attr(the_thing, "$attr1$attr2$attr3")。似乎这应该是可能的,但我不知所措。

例如,我正在编写一些代码来使用来自 Github API 的响应。有一堆函数,比如(这些非常简化,只是为了举例):

get_milestone <- function(org, repo) {
        response <- graphql_query(org = org, repo = repo)
        return(response$repository$milestone$issues)
}
get_pull_request <- function(org, repo) {
        response <- graphql_query(org = org, repo = repo)
        return(response$repository$pull_request$issues)
}
get_issues <- function(org, repo) {
        response <- graphql_query(org = org, repo = repo)
        return(response$repository$issues)
}

您会注意到唯一的区别是您从响应中提取了哪些属性。

我想做一个简单的辅助函数,比如

get_something <- function(org, repo, attr_to_get) {
        response <- graphql_query(org = org, repo = repo)
        return(attr(response, attr_to_get))
}

然后每次都调用它

get_something(org, repo, attr_to_get="$repository$milestone$issues")
get_something(org, repo, attr_to_get="$repository$pull_request$issues")
get_something(org, repo, attr_to_get="$repository$issues")

但是那个语法不起作用。

有没有办法传递一个字符串来指定从对象中提取的嵌套属性?我觉得 rlang 或类似的东西可能是相关的,但我似乎无法弄清楚。

我最初的想法就是做这样的事情

param_list <- unlist(strsplit(attr_to_get, "\\$"))
for (p in param_list) {
    if (p != "") {
       response <- response[[p]]
    }
}

但这对我来说感觉非常丑陋和愚蠢。就像,必须有一种单线的方式来做到这一点,而无需手动迭代。但也许我应该那样做?非常感谢任何帮助。

为了重现性,您可以将我的函数中的 response &lt;- graphql_query(org = org, repo = repo) 行替换为 response &lt;- list(repository = list(milestone = list(issues=c("issue1", "issue2", "issue3")))) 之类的内容,然后尝试从响应中提取 "$repository$milestone$issues"。 谢谢!

【问题讨论】:

  • first $repository$milestone$issues 不是属性。它只是一个嵌套列表。你是在处理嵌套列表还是attributes??
  • 我正在处理嵌套列表。
  • 好吧,只需使用向量而不是字符串,例如response[[c("repository","milestone","issues")]]
  • 完美。这样可行。随意回答,我会接受。虽然我想我应该将问题修改为明确关于嵌套列表。
  • purrr:pluck 函数对于从嵌套列表中提取元素也很有帮助。

标签: r


【解决方案1】:

你可以的

 nm <- c("repository","milestone","issues")
 response[[nm]]

我们也可以使用purrr::pluck函数

  purrr::pluck(response, !!!nm)

【讨论】:

  • 同样,purrr::pluck(response, "repository", "milestone", "issues")
【解决方案2】:

如果您想使用rlang,这里有另一个可能的答案:

# Something generic that produces a nested list with the names you specified
graphql_query <- function(org, repo){
list(repository = list(milestone = list(issues = 'hi')))
}

get_something <- function(org, repo, ...) {
response <- graphql_query(org, repo)
attr_to_get <- paste0('response$', paste(rlang::list2(...), collapse = '$'))
rlang::eval_tidy(rlang::parse_expr(attr_to_get))
}

get_something('org', 'repo', 'repository', 'milestone', 'issues')
>>> [1] "hi"

或者你可以这样做:

att_lst <- c('repository', 'milestone', 'issues')
get_something('org', 'repo', !!!att_lst)
>>> [1] "hi"

【讨论】:

  • 我强烈建议不要使用parse_expr。构建代码字符串并执行它们可能是混乱和危险的。特别是考虑到其他答案已经显示了安全的内置方法来实现这一点。
【解决方案3】:

另一个基本 R 解决方案是使用 Reduce() + [[

Reduce(`[[`,list(response,"repository","milestone","issues"))

Reduce(`[[`,list(response,c("repository","milestone","issues")))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 2020-12-09
    相关资源
    最近更新 更多