r - 如何使用变量名创建未知深度列表?
问题描述
我想创建一个未知深度的列表。
这在某种程度上与我的另一个问题有关(将函数应用于参数网格并返回 purrr 中的列表列表),但我认为这可能值得自己发表。
在犯了一些错误之后,我发现可以通过编写以下代码来创建这样的列表:
rtn = list()
rtn$a$f$t=6
rtn
这给出了深度 4 的列表(根据purrr:vec_depth(rtn)
),这正是预期的输出。
$a $a$f $a$f$t [1] 6
不幸的是,当我尝试使用名称时,rtn[["a"]][["f"]][["t"]]="6"
没有用:
$a f "6"
这里,rtn
是一个简单向量的列表rtn$a
,并且“t”索引被删除。
阅读时,我注意到有一章关于“递归(类列表)对象”,其中说明了和?Extract
之间的区别:[[<-
$<-
当
$<-
应用于 aNULL
x
时,它首先强制x
转换为list()
。[[<-
如果替换值value
的长度大于 1 ,也会发生这种情况:如果value
长度为 1 或 0,x
则首先将其强制为值类型的零长度向量。
我怎么能用变量构造这样一个列表?(最好使用 base R 或任何tidyverse
/rlang
包)
到目前为止,这是我的尝试:
免责声明:这可能是我写过的最丑陋的代码之一,这个操作符重新分配(这并不完全有效),但谁知道呢,它可能会带来更好的东西......
`[[<-`=`$<-` #yuck...
rtn = list()
rtn$a$f$t=6
rtn[["a"]][["f"]][["t"]]="6" #this works!
xx="b"
rtn[[xx]][["f"]][["t"]]="6" #but this does not: unexpectedly it creates a level "xx" instead of "b"
rm(`[[<-`) #better safe than sorry
rtn
解决方案
解决此类问题的一种直接方法是使用递归函数。一种方法是(完全编辑的原始帖子):
ff = function(nms, val, init = list())
{
if(!length(nms)) return(val)
init[[nms[1]]] = c(init[[nms[1]]], ff(nms[-1], val))
return(init)
}
在更新现有列表时对其进行测试:
rtn = list()
rtn$a$f$t = 6
rtn$a$j$r = 19
rtn$b$r = 3
rtn$b$v$f$w = 42
rtn$c$e = 11
rtn2 = ff(c("a", "f", "t"), 6)
rtn2 = ff(c("a", "j", "r"), 19, rtn2)
rtn2 = ff(c("b", "r"), 3, rtn2)
rtn2 = ff(c("b", "v", "f", "w"), 42, rtn2)
rtn2 = ff(c("c", "e"), 11, rtn2)
identical(rtn, rtn2)
#[1] TRUE
推荐阅读
- .net-core - InvalidOperationException:无法使用 EF dbcontext 解析类型的服务
- javascript - 具有完整 ajax 烧瓶实现的按钮完全没有做任何事情
- reactjs - 如何在 reducer 中访问 redux 表单中的值?
- android - 如何在 kotlin 中实现 RecyclerViewPager?
- google-apps-script - 我在这个脚本上做错了什么?它说“在对象电子表格中找不到函数 createMenu。”
- c++ - 如何在网格视图中确定单击的项目
- c# - 统一套接字通信时的错误避免
- python - 在 Python 中通过数组调用时,调度时间被调度模块覆盖
- spring-batch - 如何在 Spring Cloud Data Flow 中为 Spring Batch 作业设置调度程序?
- amazon-web-services - Cloudwatch 自定义事件未触发