R:将嵌套的for循环转换为应用函数

时间:2020-03-29 22:30:56

标签: r lapply purrr

这是我的最小示例:

calA_fun <- function(list_A){
for (k in 1:length(list_A)){
  out_level = list()
  out_level[[k]] <- unlist( lapply(list_A[[k]], sqrt) )
  for (j in 1:length(list_A[[k]]) ){
      out_level_level = list()
      out_level_level[[j]] <- lapply(list_A[[k]][[j]], function(x) x+ out_level[[k]] ) 
      print(out_level_level[[j]])
  }
}
}
list_A <- list(aa = c(1, 2, 4), bb = c(6,2))
calA_fun(list_A)

我正在使用apply()系列或map()重写此函数以替换for循环,但是我不知道是否可行,因为j嵌套在k中,所以它是一个层次结构。

谢谢!

3 个答案:

答案 0 :(得分:3)

我们可以使用rapply(递归应用),它正是为此任务而构建的。

使用@Marcelo Fernando Befumo的数据

rapply(xx, sum)
#   aa    bb cc.a2 cc.b2 cc.a3 cc.b3 
#   45   145   110     0   275    54 

或者如果您想输出为列表

rapply(xx, sum, how = "list")

#$aa
#[1] 45

#$bb
#[1] 145

#$cc
#$cc$a2
#[1] 110

#$cc$b2
#[1] 0

#$cc[[3]]
#$cc[[3]]$a3
#[1] 275

#$cc[[3]]$b3
#[1] 54

答案 1 :(得分:1)

更新:拆分并增加可读性的解决方案:

calA_fun <- function (list_A) {
  Reduce(c, list_to_sums(list_A))
}

list_to_sums <- function (list_A) {
  lapply(val_and_sqrt(list_A), get_sums)
}

val_and_sqrt <- function (list_A) {
  lapply(list_A, function (x) {
    list(val = x, sqrt = sqrt(x))
  })
}

get_sums <- function(l) {
  lapply(l$val, function(x) { x + l$sqrt })
}

(原始溶液)

calA_fun <- function(list_A) {
  Reduce(
    c,    # make flat list
    lapply(
      lapply(list_A, function (x) { list(x, sqrt(x)) }),  # calculate sqrt
      function(x) {       # process every outer-level list item
        lapply(x[[1]], function (y) { y + x[[2]] })  # replace with vector of each square root + raw value y
      }
    )
  )
}

答案 2 :(得分:1)

递归函数可以与任意嵌套一起使用

recursiveListSum <- function(x) {
  if (is.list(x)) {
    lapply(x, recursiveListSum)  
  } else {
    sum(x)
  }
}

xx <- list(
  "aa" = 1:9,
  "bb" = 10:19,
  "cc" = list(
    "a2" = 5:15,
    "b2" = -2:2,
    list(
      "a3" = 20:30,
      "b3" = -1:10
    )
  )
) 
# results
> recursiveListSum(xx)
$aa
[1] 45

$bb
[1] 145

$cc
$cc$a2
[1] 110

$cc$b2
[1] 0

$cc[[3]]
$cc[[3]]$a3
[1] 275

$cc[[3]]$b3
[1] 54