R-在“ purrr”中的列表上递归地应用函数,同时保留其结构

时间:2019-06-08 09:53:14

标签: 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中递归地应用函数来实现上述目的?我知道reduceaccumulate函数以及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

1 个答案:

答案 0 :(得分:1)

我们可以定义一个递归函数,为每个(嵌套的)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

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