使用Reduce调用函数列表

r.u*_*apr 1 r filter

我想在向量上使用过滤器列表.我的问题是,filter_list在这个例子中,我如何使用Reduce(或其他基本R标准函数)来执行递归函数正在做的事情(=应用所有函数和逻辑AND连接):

my_vec <- c("AAffff1", "AAafszx223", "AAasfe2XX", "uuse3", "AA232fiserf", "ffse1211", "766", "AA33")

filter_list <- list(
  f_1 = function(x) {substr(x, 1, 2) == "AA"},
  f_2 = function(x) {grepl("\\d{3,}", x)},
  f_3 = function(x) {nchar(x) >= 5})

my_call <- function(fun_list, x) {
  if (length(fun_list) == 1) {
    fun_list[[1]](x) 
  } else {
    my_call(fun_list[-length(fun_list)], x) & fun_list[[length(fun_list)]](x)
  }
}
my_vec[my_call(filter_list, my_vec)]
# [1] "AAafszx223"  "AA232fiserf" --> ok

my_vec[Reduce(function(f, ...) f(...), filter_list, my_vec, right = TRUE)]
# character(0) --> wrong
Run Code Online (Sandbox Code Playgroud)

G. *_*eck 6

这是一些替代方案.全部仅使用基础R.(2)用途Reduce.(4)具有最短的代码.(3)似乎特别简单.

1)外部你实际上并不需要Reduce这个.使用outer来创建,其第i行和如果施加到的第j个元素的第i个函数j列是TRUE的逻辑矩阵my_vec是TRUE,然后从使用apply来创建,其第j个元素为TRUE,如果在第j列中的所有元素都为TRUE的逻辑矢量最后下标my_vec.

call_fun <- function(fun, x) fun(x)
my_vec[ apply(outer(filter_list, my_vec, Vectorize(call_fun)), 2, all) ]
## "AAafszx223"  "AA232fiserf"
Run Code Online (Sandbox Code Playgroud)

2)减少另一方面我们当然可以使用Reduce.创建一个函数,该函数接受一个字符串并filter_list使用ReduceAND结果调用其中的每个函数.然后用于Filter提取my_vec该函数的应用程序赋予TRUE的那些元素.

Filter(function(x) Reduce(`&`, lapply(filter_list, do.call, list(x))), my_vec)
## [1] "AAafszx223"  "AA232fiserf"
Run Code Online (Sandbox Code Playgroud)

3)所有 实际上我们可以Reduce通过使用all和几乎相同的代码来消除(2).

Filter(function(x) all(sapply(filter_list, do.call, list(x))), my_vec)
## [1] "AAafszx223"  "AA232fiserf"
Run Code Online (Sandbox Code Playgroud)

4)另一种变化如下.sapply创建一个类似但从(1)中的矩阵转置的矩阵,然后我们应用于all它的行和下标.

my_vec[ apply(sapply(filter_list, do.call, list(my_vec)), 1, all) ]
[1] "AAafszx223"  "AA232fiserf"
Run Code Online (Sandbox Code Playgroud)

5)double sapply这个使用上面的想法,但在使用double时更加对称sapply:

my_vec[ sapply(my_vec, function(x) all(sapply(filter_list, do.call, list(x)))) ]
## [1] "AAafszx223"  "AA232fiserf"
Run Code Online (Sandbox Code Playgroud)