purrr::map()与rlang::as_label()/rlang::ensym()配合失效问题
在purrr::map中获取原始对象名称的解决方案
你的核心问题在于:rlang::ensym()是捕获调用时传入的符号名称,而使用purrr::map()遍历值列表时,传递给function1的是匿名函数的参数(.或x),而非原始对象的符号,因此返回的是参数名而非预期的对象名。
问题根源解析
list(input1)存储的是input1的值(即"a"),而非input1这个符号本身。- 当你用
map(list(input1), ~function1(.))时,.代表列表中的元素值,ensym(.)捕获的是匿名函数里的参数符号.,所以返回"."。 - 同理
function(x) function1(x)中,ensym(x)捕获的是参数符号x,返回"x"。
可行解决方案
方法1:直接传递符号列表
将需要处理的对象以符号形式传入map,而非传递值:
library(purrr) library(rlang) function1 <- function(input) { rlang::as_label(rlang::ensym(input)) } input1 <- "a" input2 <- "b" # 直接传入对象符号,而非值 output <- purrr::map(list(input1, input2), function1) output # 输出:[[1]] "input1" [[2]] "input2"
方法2:使用带命名的列表+imap
如果需要基于值列表处理,给列表添加对象名称,再用purrr::imap()直接提取名称(最稳妥的方式):
# 创建带命名的对象列表 input_list <- list(input1 = input1, input2 = input2) # imap的第二个参数.y对应列表的名称 output <- purrr::imap(input_list, ~.y) output # 输出:$input1 "input1" $input2 "input2"
方法3:修改函数兼容符号与值
如果需要函数同时支持符号和值输入,可添加判断逻辑(但值输入需依赖命名列表):
function1 <- function(input) { if (rlang::is_symbol(input)) { rlang::as_label(input) } else { # 从调用环境中反向查找值对应的对象名(仅适用于单一值无重复的场景) obj_name <- ls(envir = rlang::caller_env())[sapply(ls(envir = rlang::caller_env()), function(x) get(x) == input)] if (length(obj_name) == 1) obj_name else stop("无法唯一匹配对象名称") } } # 符号调用 function1(input1) # 返回"input1" # 值调用(需确保当前环境中该值唯一) purrr::map(list(input1), function1) # 返回[[1]] "input1"
内容的提问来源于stack exchange,提问作者srathnavel
相关产品推荐
相关产品推荐

