purrr::flatten 一个列表但保留层次名称

purrr::flatten a list but maintain the hierarchy name

假设我有一个命名向量列表:

test_list <- list("grp1" = c(subgrp1 = "A", subgrp2 = "B"),
                  "grp2" = c(subgrp1 = "A", subgrp2 = "B"), 
                  "grp3" = c(subgrp1 = "A"))

我想把这个改成

want_list <- list("grp1 - subgrp1" = c(subgrp1 = "A"),
                  "grp1 - subgrp2" = c(subgrp2 = "B"),
                  "grp2 - subgrp1" = c(subgrp1 = "A"),
                  "grp2 - subgrp2" = c(subgrp2 = "B"),
                  "grp3" = c(subgrp1 = "A"))

purrr::flatten(test_list) returns 长度为 5 的列表,但完全失去了“grp”层次结构——这并不奇怪,因为这是此函数的重点。我希望通过将名称保留在长度 >1 的名称上来“维护”层次结构。

我想你可以根据上面的层重命名命名向量中的每个元素...但我不确定当列表长度不同时如何以可扩展的方式执行此操作。

我该如何解决这个问题?

我们可能需要通过更改名称进行一些修改

want_list2 <- do.call(c, unname(Map(function(x, y) {
   lst1 <- lapply(seq_along(x), function(i) x[i])
   if(length(lst1) > 1)
    setNames(lst1, paste0(y, ' - ', names(x))) else setNames(lst1, y)
  }, test_list, names(test_list))))

-检查预期输出

> all.equal(want_list, want_list2)
[1] TRUE

或使用 flatten 和 tidyverse 选项

library(dplyr)
library(purrr)
library(stringr)
want_list3 <- imap(test_list, ~
      map(as.list(seq_along(.x)), function(i) .x[i]) %>% 
       set_names(if(length(.x) > 1) str_c(.y, ' - ', names(.x)) else
             .y)) %>%
       flatten

-测试

> all.equal(want_list, want_list3)
[1] TRUE