在 R 中的嵌套列表中分配具有相同名称的值
Assign values with same name in a nested list in R
我想为嵌套列表中具有相同名称的特定元素分配相同的值。如果嵌套列表中不存在该元素,我也想创建它,但这在我的示例中没有显示。
例如,假设我有:
ls <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
b = list(e1 = "value2.1", e2 = "value2.2"))
我想将值 "same value" 分配给名为 e1
的子列表中的所有元素,这样我最终会得到这个 所需的输出:
list(a = list(e1 = "same value", e2 = "value1.2"),
b = list(e1 = "same value", e2 = "value2.2")
> ls
$a
$a$e1
[1] "same value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "same value"
$b$e2
[1] "value2.2"
经过研究,我发现包 purrr
中的函数 modify_depth()
将函数应用于嵌套列表,但不会分配值。
我唯一的其他解决方案是这样做:
ls2 <- list()
for(sublist in ls){
sublist[["e1"]] <- "same value"
ls2 <- c(ls2, list(sublist))
}
names(ls2) <- names(ls)
ls <- ls2
rm(ls2)
注意:循环后"same value"在ls中没有赋值,所以我要创建ls2
。我可以使它成为一个函数,但我确信有更好的方法可以做到这一点,而无需 for
循环。
感谢您的帮助!
我们可以使用 lapply
遍历列表元素,然后使用 [
和逻辑运算符来实现相等性 ==
我们可以找到我们想要更改的值
> lapply(ls, function(x){
x[names(x)=="e1"] <- "same.value"
x
} )
$`a`
$`a`$`e1`
[1] "same.value"
$`a`$e2
[1] "value1.2"
$b
$b$`e1`
[1] "same.value"
$b$e2
[1] "value2.2"
来自 purrr
的 map
和 replace
:
library(purrr)
map(ls, ~replace(., "e1", "same value"))
或 modify_depth
:
modify_depth(ls, 1, ~replace(., "e1", "same value"))
replace
也适用于 lapply
:
lapply(ls, replace, "e1", "same value")
输出:
$a
$a$e1
[1] "same value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "same value"
$b$e2
[1] "value2.2"
modify_depth
的好处是你可以选择深度,而map
和lapply
只下降一级:
ls2 <- list(c = list(a1 = list(e1 = "value1.1", e2 = "value1.2")),
d = list(a1 = list(e1 = "value2.1", e2 = "value2.2")))
modify_depth(ls2, 2, ~replace(., "e1", "same value"))
输出:
$c
$c$a1
$c$a1$e1
[1] "same value"
$c$a1$e2
[1] "value1.2"
$d
$d$a1
$d$a1$e1
[1] "same value"
$d$a1$e2
[1] "value2.2"
编辑: 如果我们想将值向量应用于 ls2
的每个 e1
元素,modify_depth
将不起作用,因为它没有 map2
变体。相反,我会使用两层 map
,在顶层使用 map2
,在第二层使用 map
。
vec <- c("newvalue1.1", "newvalue2.1")
map2(ls2, vec, ~map(.x, replace, "e1", .y))
输出:
$c
$c$a1
$c$a1$e1
[1] "newvalue1.1"
$c$a1$e2
[1] "value1.2"
$d
$d$a1
$d$a1$e1
[1] "newvalue2.1"
$d$a1$e2
[1] "value2.2"
ls
在 R 中保留,所以我建议为列表使用另一个名称,我的替代方案是:
y <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
b = list(e1 = "value2.1", e2 = "value2.2"))
lapply(y, function(x) replace(x, list = "e1", values = "new value"))
$a
$a$e1
[1] "new value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "new value"
$b$e2
[1] "value2.2"
我想为嵌套列表中具有相同名称的特定元素分配相同的值。如果嵌套列表中不存在该元素,我也想创建它,但这在我的示例中没有显示。
例如,假设我有:
ls <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
b = list(e1 = "value2.1", e2 = "value2.2"))
我想将值 "same value" 分配给名为 e1
的子列表中的所有元素,这样我最终会得到这个 所需的输出:
list(a = list(e1 = "same value", e2 = "value1.2"),
b = list(e1 = "same value", e2 = "value2.2")
> ls
$a
$a$e1
[1] "same value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "same value"
$b$e2
[1] "value2.2"
经过研究,我发现包 purrr
中的函数 modify_depth()
将函数应用于嵌套列表,但不会分配值。
我唯一的其他解决方案是这样做:
ls2 <- list()
for(sublist in ls){
sublist[["e1"]] <- "same value"
ls2 <- c(ls2, list(sublist))
}
names(ls2) <- names(ls)
ls <- ls2
rm(ls2)
注意:循环后"same value"在ls中没有赋值,所以我要创建ls2
。我可以使它成为一个函数,但我确信有更好的方法可以做到这一点,而无需 for
循环。
感谢您的帮助!
我们可以使用 lapply
遍历列表元素,然后使用 [
和逻辑运算符来实现相等性 ==
我们可以找到我们想要更改的值
> lapply(ls, function(x){
x[names(x)=="e1"] <- "same.value"
x
} )
$`a`
$`a`$`e1`
[1] "same.value"
$`a`$e2
[1] "value1.2"
$b
$b$`e1`
[1] "same.value"
$b$e2
[1] "value2.2"
来自 purrr
的 map
和 replace
:
library(purrr)
map(ls, ~replace(., "e1", "same value"))
或 modify_depth
:
modify_depth(ls, 1, ~replace(., "e1", "same value"))
replace
也适用于 lapply
:
lapply(ls, replace, "e1", "same value")
输出:
$a
$a$e1
[1] "same value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "same value"
$b$e2
[1] "value2.2"
modify_depth
的好处是你可以选择深度,而map
和lapply
只下降一级:
ls2 <- list(c = list(a1 = list(e1 = "value1.1", e2 = "value1.2")),
d = list(a1 = list(e1 = "value2.1", e2 = "value2.2")))
modify_depth(ls2, 2, ~replace(., "e1", "same value"))
输出:
$c
$c$a1
$c$a1$e1
[1] "same value"
$c$a1$e2
[1] "value1.2"
$d
$d$a1
$d$a1$e1
[1] "same value"
$d$a1$e2
[1] "value2.2"
编辑: 如果我们想将值向量应用于 ls2
的每个 e1
元素,modify_depth
将不起作用,因为它没有 map2
变体。相反,我会使用两层 map
,在顶层使用 map2
,在第二层使用 map
。
vec <- c("newvalue1.1", "newvalue2.1")
map2(ls2, vec, ~map(.x, replace, "e1", .y))
输出:
$c
$c$a1
$c$a1$e1
[1] "newvalue1.1"
$c$a1$e2
[1] "value1.2"
$d
$d$a1
$d$a1$e1
[1] "newvalue2.1"
$d$a1$e2
[1] "value2.2"
ls
在 R 中保留,所以我建议为列表使用另一个名称,我的替代方案是:
y <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
b = list(e1 = "value2.1", e2 = "value2.2"))
lapply(y, function(x) replace(x, list = "e1", values = "new value"))
$a
$a$e1
[1] "new value"
$a$e2
[1] "value1.2"
$b
$b$e1
[1] "new value"
$b$e2
[1] "value2.2"