首页 > 解决方案 > R - 在“purrr”中的列表上递归应用函数,同时保留其结构

问题描述

我有以下列表:

my_list = split(1:3, letters[1:3]) %>% 
  map(as.list) %>% 
  str()

List of 3
 $ a:List of 1
  ..$ : int 1
 $ b:List of 1
  ..$ : int 2
 $ c:List of 1
  ..$ : int 3

我想设置xyz列表的每个元素列表本身的属性。我目前正在接受:

my_list = split(1:3, letters[1:3]) %>% 
  map(., ~.x %>% 
        as.list %>% 
        structure(xyz = T)) %>% 
  structure(xyz = T)

但我想知道如果列表更深我会做什么?有没有办法递归地应用函数来实现上述功能purrr?我知道reduceandaccumulate功能和rapply基础,但我不认为他们在这种情况下做我需要的。

此外,尝试 rapply 给了我:

my_list = rapply(my_list, function(x) structure(x, xyz = T), how = 'list') %>% str()
List of 3
 $ a:List of 1
  ..$ : int 1
  .. ..- attr(*, "xyz")= logi TRUE
 $ b:List of 1
  ..$ : int 2
  .. ..- attr(*, "xyz")= logi TRUE
 $ c:List of 1
  ..$ : int 3
  .. ..- attr(*, "xyz")= logi TRUE

这似乎让我接近预期的结果。但是attr(my_list, 'xyz')两者attr(my_list$a, 'xyz')都产生了NULL,这是为什么呢?两者都是为了我的帖子前面包含的管道的结果attr(my_list, 'xyz')attr(my_list$a, 'xyz')TRUE

标签: rpurrr

解决方案


我们可以定义一个递归函数来为每个(嵌套)list 每个嵌套list元素添加一个属性。

recursive_add_attr <- function(this) {
    if (is.list(this))
        structure(map(this, recursive_add_attr), xyz = TRUE)
    else
        structure(this, xyz = TRUE)
}

out <- recursive_add_attr(my_list)
str(out)
#List of 3
# $ a:List of 1
#  ..$ : int 1
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..- attr(*, "xyz")= logi TRUE
# $ b:List of 1
#  ..$ : int 2
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..- attr(*, "xyz")= logi TRUE
# $ c:List of 1
#  ..$ : int 3
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..- attr(*, "xyz")= logi TRUE
# - attr(*, "xyz")= logi TRUE

这也适用于list任意深度和嵌套结构的 s:

my_list2 <- list(
    a = list(A1 = 1, A2 = list(2, 3)),
    b = list(B1 = 4, B2 = list(5, 6)))
out2 <- recursive_add_attr(my_list2)
str(out2)
#List of 2
# $ a:List of 2
#  ..$ A1: num 1
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..$ A2:List of 2
#  .. ..$ : num 2
#  .. .. ..- attr(*, "xyz")= logi TRUE
#  .. ..$ : num 3
#  .. .. ..- attr(*, "xyz")= logi TRUE
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..- attr(*, "xyz")= logi TRUE
# $ b:List of 2
#  ..$ B1: num 4
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..$ B2:List of 2
#  .. ..$ : num 5
#  .. .. ..- attr(*, "xyz")= logi TRUE
#  .. ..$ : num 6
#  .. .. ..- attr(*, "xyz")= logi TRUE
#  .. ..- attr(*, "xyz")= logi TRUE
#  ..- attr(*, "xyz")= logi TRUE
# - attr(*, "xyz")= logi TRUE

推荐阅读