如何在R语言中高效优雅地根据嵌套元素名称确定其所属列表?
查找嵌套列表中元素所属的上层列表名称
我有一个包含可迭代元素的列表:
my_list <- list( A = list(apple = 1:3, orange = "abc"), B = tibble(banana = "qwerty", strawberry = 1:5), C = data.frame(blueberry = "xyz", mango = "something") )
我希望查询某个元素(如"blueberry")所属的上层列表名称,比如输入"blueberry"应返回"C"。我已编写以下函数,想了解是否有更优雅(高效)的解决方案:
find_list <- function(name, my_list) { idx <- which(sapply(my_list, function(x) name %in% names(x))) if (length(idx) > 0) { return(names(my_list)[idx]) } else { return(NULL) } } # 测试 print(find_list("strawberry", my_list)) # 输出 "B" print(find_list("mango", my_list)) # 输出 "C" print(find_list("apple", my_list)) # 输出 "A" print(find_list("nonexistent", my_list)) # 未找到时输出 NULL
几种优化方案
1. Base R 简洁版
去掉which直接用逻辑向量索引,代码更紧凑:
find_list <- function(name, my_list) { res <- names(my_list)[sapply(my_list, \(x) name %in% names(x))] if (length(res) == 0) NULL else res }
2. Base R 高效版(vapply)
处理大规模列表时,vapply比sapply性能更优——它提前指定返回类型,避免了类型推断的额外开销:
find_list <- function(name, my_list) { res <- names(my_list)[vapply(my_list, \(x) name %in% names(x), logical(1))] if (length(res) == 0) NULL else res }
3. tidyverse/purrr 风格版
如果熟悉tidyverse生态,用purrr函数可以让代码更具可读性:
library(purrr) find_list <- function(name, my_list) { matches <- imap_lgl(my_list, ~ name %in% names(.x)) res <- names(matches[matches]) if (length(res) == 0) NULL else res }
说明
你原本的函数已经逻辑清晰、易于维护。上述优化主要在代码简洁度或大列表场景下的效率上做了提升:
- 简洁版去掉冗余的
which调用,直接通过逻辑向量筛选目标名称; vapply版本适合处理超大列表,性能优于sapply;- purrr风格版更符合tidyverse用户的编码习惯,可读性更强。
所有优化版本的测试结果都和原函数一致:未找到元素时返回NULL,找到时返回对应的上层列表名称。
内容的提问来源于stack exchange,提问作者Aku-Ville Lehtimäki
相关产品推荐
相关产品推荐

