如何通过整数向量程序化更新嵌套列表指定位置的值?
程序化修改嵌套列表指定位置的值
问题背景
现有嵌套列表:
x = list(a1 = list(b1 = list(c1 = 1), b2 = list(d1 = 1, d2 = 2, d3 = 3)))
以及用于指定嵌套位置的索引向量和待更新值:
index = c(1,1,1) # 目标为更新c1 value = 100
手动更新可采用以下方式:
x[[1]][[1]][1] = value x
或:
index = c(1,2,2) # 目标为更新d2 `[[`(`[[`(`[[`(x, 1), 2), 2) = value x
需求是通过程序化方法,利用索引向量设置嵌套列表对应位置的值。
目前仅读取对应位置值可通过以下方法实现,但无法用于修改:
ifuns <- lapply(index, function(i) {function(x) `[[`(x, i)}) Funcall <- function(f, ...) f(...) Reduce(Funcall, rev(ifuns), x, right = TRUE)
尝试直接赋值会触发报错:
Reduce(Funcall, rev(ifuns), x, right = TRUE) <- value
报错信息:
Error in Reduce(Funcall, rev(ifuns), x, right = TRUE) <- value : could not find function "Reduce<-"
解决方案
方法1:递归遍历赋值
编写递归函数,遍历至索引的倒数第二层,再对目标位置赋值:
set_nested_value <- function(x, index, value) { if (length(index) == 1) { x[[index]] <- value return(x) } x[[index[1]]] <- set_nested_value(x[[index[1]]], index[-1], value) x } # 测试更新c1 x = list(a1 = list(b1 = list(c1 = 1), b2 = list(d1 = 1, d2 = 2, d3 = 3))) index = c(1,1,1) value = 100 x <- set_nested_value(x, index, value) print(x)
输出结果:
$a1 $a1$b1 $a1$b1$c1 [1] 100 $a1$b2 $a1$b2$d1 [1] 1 $a1$b2$d2 [1] 2 $a1$b2$d3 [1] 3
方法2:构造[[调用链获取父层级
通过构造调用链获取目标位置的父层级,再直接赋值:
set_nested_value <- function(x, index, value) { # 构造获取父层级的调用表达式 parent_call <- as.call(c(list(quote(`[[`)), x, index[-length(index)])) # 获取父层级对象(引用传递) parent_obj <- eval.parent(parent_call) # 对父层级的目标位置赋值 parent_obj[[index[length(index)]]] <- value x } # 测试更新d2 x = list(a1 = list(b1 = list(c1 = 1), b2 = list(d1 = 1, d2 = 2, d3 = 3))) index = c(1,2,2) value = 200 x <- set_nested_value(x, index, value) print(x)
输出结果:
$a1 $a1$b1 $a1$b1$c1 [1] 1 $a1$b2 $a1$b2$d1 [1] 1 $a1$b2$d2 [1] 200 $a1$b2$d3 [1] 3
方法3:使用purrr包的pluck<-函数
若允许使用tidyverse工具,purrr包的pluck<-可直接实现需求:
library(purrr) x = list(a1 = list(b1 = list(c1 = 1), b2 = list(d1 = 1, d2 = 2, d3 = 3))) index = c(1,1,1) value = 100 pluck(x, !!!index) <- value print(x)
内容的提问来源于stack exchange,提问作者jakob-r
相关产品推荐
相关产品推荐

