You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言:使用set_names结合map构建目录嵌套列表失败问题

问题描述

首先创建测试目录结构:

c("Level1/Level1A/Level1AA", 
  "Level1/Level1A/Level1AB", 
  "Level1/Level1B/Level1BA", 
  "Level1/Level1B/Level1BB",
  "Level2/Level2A/Level2AA", 
  "Level2/Level2A/Level2AB", 
  "Level2/Level2B/Level2BA", 
  "Level2/Level2B/Level2BB") %>% 
  map(dir.create, recursive = T)

需要生成与该目录结构一致的命名嵌套列表,且必须采用tidyverse风格。

前期尝试的代码运行正常:

list.dirs(recursive = F) %>% 
  map(list.dirs, recursive = F) %>% 
  set_names(str_split(., "/") %>% 
              map(pluck, 2))

输出结果符合预期:

$Level1
[1] "./Level1/Level1A" "./Level1/Level1B"

$Level2
[1] "./Level2/Level2A" "./Level2/Level2B"

但继续构建下一级列表时,代码运行出错:

list.dirs(recursive = F) %>% 
  map(list.dirs, recursive = F) %>% 
  set_names(str_split(., "/") %>% 
              map(pluck, 2)) %>% 
  map_depth(2, list.dirs, recursive = F) %>% 
  map(set_names, str_split(., "/") %>% 
        map_depth(2, pluck, 3))

错误输出中,子级列表的名称变成了list(NULL, NULL, ...),而非预期的Level1A这类名称:

$Level1
$Level1$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level1/Level1A/Level1AA" "./Level1/Level1A/Level1AB"

$Level1$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level1/Level1B/Level1BA" "./Level1/Level1B/Level1BB"


$Level2
$Level2$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level2/Level2A/Level2AA" "./Level2/Level2A/Level2AB"

$Level2$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level2/Level2B/Level2BA" "./Level2/Level2B/Level2BB"

期望输出结构:

list(Level1 = list(Level1A = c("Level1AA", "Level1AB"),
                   Level1B = c("Level1BA", "Level1BB")),
     Level2 = list(Level2A = c("Level2AA", "Level2AB"),
                   Level2B = c("Level2BA", "Level2BB")))
解决方案

之前的错误在于set_names的使用时机和层级处理逻辑有误,应该在每一层级遍历的同时完成路径提取和命名,同时处理最底层的目录名称。

以下是正确的tidyverse风格管道代码:

list.dirs(recursive = TRUE, full.names = FALSE) %>%
  # 过滤掉根目录
  discard(~ . == ".") %>%
  # 将每个目录路径拆分为三级层级部分
  map(str_split_fixed, pattern = "/", n = 3) %>%
  # 转换为数据框方便分组处理
  bind_rows() %>%
  set_names(c("level1", "level2", "level3")) %>%
  # 按一级、二级目录分组,收集三级目录为向量
  group_by(level1, level2) %>%
  summarise(level3 = list(level3), .groups = "drop") %>%
  # 按一级目录分组,将二级目录与对应三级列表组合为嵌套子列表
  group_by(level1) %>%
  summarise(nested = list(deframe(tibble(level2, level3))), .groups = "drop") %>%
  # 转换为最终的命名嵌套列表
  deframe()

代码说明

  1. 用list.dirs获取所有目录,通过full.names = FALSE只保留相对路径名称,同时过滤掉根目录.;
  2. 将每个路径拆分为三级目录部分,转换为数据框后按一级、二级目录分组;
  3. 分组后将三级目录收集为向量,再以二级目录为名称、三级向量为值构建子列表;
  4. 最后通过deframe将一级目录设为顶级列表的名称,得到符合要求的嵌套结构。

运行上述代码后,输出结果与期望结构完全一致。

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:50:37