不区分大小写地评估裸露表达式

问题描述 投票:0回答:1

我想创建一个函数来检查向量中是否包含裸表达式。该函数应该独立于输入数据的情况而工作。

评估各种表达式的一个简单解决方案是使用

tidyselect::eval_select()
。例如。这是一个虚拟函数,用于检查表达式是否为
a
b
c

is_abc <- function(...) {
  expr <- rlang::expr(c(...))
  data <- rlang::set_names(letters)
  out <- tidyselect::eval_select(expr, data)
  names(out) %in% letters[1:3]
}

is_abc(a, b, z)
#> [1]  TRUE  TRUE FALSE

is_abc(c(a, b, z))
#> [1]  TRUE  TRUE FALSE

reprex 包于 2023 年 12 月 27 日创建(v2.0.1)

问题是我认为不编辑

tidyselect::eval_select()
(或使用特殊的选择助手)就不可能使其不区分大小写。

is_abc(c(a, B, z))
#> Error in `is_abc()`:
#> ! Can't subset columns that don't exist.
#> ✖ Column `B` doesn't exist.

或者,我可以使用

rlang::enexprs()
获取符号列表,然后在更改大小写或与向量比较时将其转换为字符类型:

is_abc <- function(...) {
  exprs <- rlang::enexprs(...)
  tolower(exprs) %in% tolower(letters[1:3])
}

is_abc(a, b, z)
#> [1]  TRUE  TRUE FALSE

is_abc(a, B, z)
#> [1]  TRUE  TRUE FALSE

reprex 包于 2023 年 12 月 27 日创建(v2.0.1)

现在的问题是,这不适用于更复杂的表达式,因为这会将整个表达式转换为字符串:

is_abc(c(a, b, z))
#> [1] FALSE

是否有一个简单的解决方案可以解决这个问题,以便我可以让一个函数在两种情况下都可以工作,而不依赖于输入的情况?

例如:

# desired behaviour

is_abc(c(a, B), z)
#> [1]  TRUE  TRUE FALSE
r rlang
1个回答
0
投票

你可以在 R 基础上完成所有事情:

is_abc <- function(...) {
  args <- as.list(match.call())[-1]
  out <- unlist(lapply(args, function(x) {
    if(is.call(x)) {
      x <- as.list(x)
      if(as.character(x[[1]]) != "c") {
        stop("is_abc does not know what to do with calls to function '", 
             as.character(x[[1]]), "'")
      }
      unlist(lapply(x[-1], as.character))
    } else {
      as.character(x)
    }
  }))
  toupper(out) %in% c("A", "B", "C")
}

测试:

is_abc(a, b, z)
#> [1]  TRUE  TRUE FALSE

is_abc(A, b, z)
#> [1]  TRUE  TRUE FALSE

is_abc(c(a, b, z))
#> [1]  TRUE  TRUE FALSE

is_abc(c(a, B, z))
#> [1]  TRUE  TRUE FALSE

is_abc(c(a, B), z)
#> [1]  TRUE  TRUE FALSE
© www.soinside.com 2019 - 2024. All rights reserved.