将列表的元素附加到该列表的下一个元素
appending elements of list to the next element of that list
假设我正在处理一个列表列表,如下所示:
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
我想应用一个函数,比如:
foo <- function(x){
sum(x$a, x$b)*x$c
}
第一个列表中的元素 c
需要附加到列表中的下一个元素 (l2
) 才能使函数正常工作。所以算法是:
A) 计算 sum(a, b)
乘以 c
-> 结果为 newc
.
B) 将 newc
附加到下一个列表,称其为 c
C) 重复
我知道如何循环执行,如下:
for(i in 1:length(lol)){
s <- lol[[i]]
s[["newc"]] <- foo(s)
lol[[i]] <- list()
lol[[i]] <- s
if((i+1)<(length(lol)+1)){
lol[[i+1]][["c"]] <- lol[[i]][["newc"]]
}
}
就我而言,我必须使用更多数据(列表中的更多列表)执行此操作并迭代很多次(最少 100 次),这给了我很高的运行时间(在某些试验中大约 2 秒)。由于我需要将其用于越来越多的海量数据,因此我希望有替代此循环的方法。
编辑:感谢您的回答。不过我需要澄清一下,我的列表中同时需要 c 和 newc。之前不清楚。谢谢。
你有没有关于如何在没有循环的情况下解决这个问题的想法?
谢谢!
我不会使用循环:
lol <- lapply(lol, \(x) c(x, c=lol[[1]]$c))
lapply(lol, foo)
问题可以改写为根据列表的前一个元素更新列表的当前元素。
循环可以简化为 one-liner:
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
foo <- function(x){
sum(x$a, x$b)*x$c
}
for(i in seq_along(lol)[-1]){
lol[[i]][["c"]] <- foo(lol[[i - 1L]])
}
lol
#> $l1
#> $l1$a
#> [1] 1 2 3
#>
#> $l1$b
#> [1] 4 5 6
#>
#> $l1$c
#> [1] 2
#>
#>
#> $l2
#> $l2$a
#> [1] 1 2 3
#>
#> $l2$b
#> [1] 4 5 6
#>
#> $l2$c
#> [1] 42
#>
#>
#> $l3
#> $l3$a
#> [1] 1 2 3
#>
#> $l3$b
#> [1] 4 5 6
#>
#> $l3$c
#> [1] 882
由 reprex package (v2.0.1)
于 2022-05-11 创建
编辑
这是另一个解决方案,基于 。
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
foo <- function(x, y) {
sum(y$a, y$b)*x
}
newc <- Reduce(foo, lol[-1], init = lol[[1]][["c"]], accumulate = TRUE)
Map(\(x, newc) {x[["c"]] <- newc; x}, lol, newc)
#> $l1
#> $l1$a
#> [1] 1 2 3
#>
#> $l1$b
#> [1] 4 5 6
#>
#> $l1$c
#> [1] 2
#>
#>
#> $l2
#> $l2$a
#> [1] 1 2 3
#>
#> $l2$b
#> [1] 4 5 6
#>
#> $l2$c
#> [1] 42
#>
#>
#> $l3
#> $l3$a
#> [1] 1 2 3
#>
#> $l3$b
#> [1] 4 5 6
#>
#> $l3$c
#> [1] 882
由 reprex package (v2.0.1)
于 2022-05-11 创建
编辑 2
要在结果中也有 newc
,可以执行以下任一操作。
注意 与上述解决方案一样,解决方案具有 不同 功能 foo
。第二个是 Ritchie Sacramento 评论中的函数,现已删除,我已在上面的 Reduce/Map
解决方案中重现。
解决方案 1,newc
foo <- function(x){
sum(x$a, x$b)*x$c
}
for(i in seq_along(lol)[-1L]){
lol[[i]][["c"]] <- foo(lol[[i - 1L]])
lol[[i]][["newc"]] <- foo(lol[[i]])
}
lol
解决方案 2,newc
foo <- function(x, y) {
sum(y$a, y$b)*x
}
newc <- Reduce(foo, lol, init = lol[[1]][["c"]], accumulate = TRUE)
Map(\(x, c, newc) {
x[["c"]] <- c
x[["newc"]] <- newc
x
}, lol, newc[-length(newc)], newc[-1])
lol
假设我正在处理一个列表列表,如下所示:
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
我想应用一个函数,比如:
foo <- function(x){
sum(x$a, x$b)*x$c
}
第一个列表中的元素 c
需要附加到列表中的下一个元素 (l2
) 才能使函数正常工作。所以算法是:
A) 计算 sum(a, b)
乘以 c
-> 结果为 newc
.
B) 将 newc
附加到下一个列表,称其为 c
C) 重复
我知道如何循环执行,如下:
for(i in 1:length(lol)){
s <- lol[[i]]
s[["newc"]] <- foo(s)
lol[[i]] <- list()
lol[[i]] <- s
if((i+1)<(length(lol)+1)){
lol[[i+1]][["c"]] <- lol[[i]][["newc"]]
}
}
就我而言,我必须使用更多数据(列表中的更多列表)执行此操作并迭代很多次(最少 100 次),这给了我很高的运行时间(在某些试验中大约 2 秒)。由于我需要将其用于越来越多的海量数据,因此我希望有替代此循环的方法。
编辑:感谢您的回答。不过我需要澄清一下,我的列表中同时需要 c 和 newc。之前不清楚。谢谢。
你有没有关于如何在没有循环的情况下解决这个问题的想法? 谢谢!
我不会使用循环:
lol <- lapply(lol, \(x) c(x, c=lol[[1]]$c))
lapply(lol, foo)
问题可以改写为根据列表的前一个元素更新列表的当前元素。
循环可以简化为 one-liner:
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
foo <- function(x){
sum(x$a, x$b)*x$c
}
for(i in seq_along(lol)[-1]){
lol[[i]][["c"]] <- foo(lol[[i - 1L]])
}
lol
#> $l1
#> $l1$a
#> [1] 1 2 3
#>
#> $l1$b
#> [1] 4 5 6
#>
#> $l1$c
#> [1] 2
#>
#>
#> $l2
#> $l2$a
#> [1] 1 2 3
#>
#> $l2$b
#> [1] 4 5 6
#>
#> $l2$c
#> [1] 42
#>
#>
#> $l3
#> $l3$a
#> [1] 1 2 3
#>
#> $l3$b
#> [1] 4 5 6
#>
#> $l3$c
#> [1] 882
由 reprex package (v2.0.1)
于 2022-05-11 创建编辑
这是另一个解决方案,基于
lol <- list(l1 = list(a = c(1:3), b = c(4:6), c = 2),
l2 = list(a = c(1:3), b = c(4:6)),
l3 = list(a = c(1:3), b = c(4:6)))
foo <- function(x, y) {
sum(y$a, y$b)*x
}
newc <- Reduce(foo, lol[-1], init = lol[[1]][["c"]], accumulate = TRUE)
Map(\(x, newc) {x[["c"]] <- newc; x}, lol, newc)
#> $l1
#> $l1$a
#> [1] 1 2 3
#>
#> $l1$b
#> [1] 4 5 6
#>
#> $l1$c
#> [1] 2
#>
#>
#> $l2
#> $l2$a
#> [1] 1 2 3
#>
#> $l2$b
#> [1] 4 5 6
#>
#> $l2$c
#> [1] 42
#>
#>
#> $l3
#> $l3$a
#> [1] 1 2 3
#>
#> $l3$b
#> [1] 4 5 6
#>
#> $l3$c
#> [1] 882
由 reprex package (v2.0.1)
于 2022-05-11 创建编辑 2
要在结果中也有 newc
,可以执行以下任一操作。
注意 与上述解决方案一样,解决方案具有 不同 功能 foo
。第二个是 Ritchie Sacramento 评论中的函数,现已删除,我已在上面的 Reduce/Map
解决方案中重现。
解决方案 1,newc
foo <- function(x){
sum(x$a, x$b)*x$c
}
for(i in seq_along(lol)[-1L]){
lol[[i]][["c"]] <- foo(lol[[i - 1L]])
lol[[i]][["newc"]] <- foo(lol[[i]])
}
lol
解决方案 2,newc
foo <- function(x, y) {
sum(y$a, y$b)*x
}
newc <- Reduce(foo, lol, init = lol[[1]][["c"]], accumulate = TRUE)
Map(\(x, c, newc) {
x[["c"]] <- c
x[["newc"]] <- newc
x
}, lol, newc[-length(newc)], newc[-1])
lol