我想在向量上使用过滤器列表.我的问题是,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)
这是一些替代方案.全部仅使用基础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
使用Reduce
AND结果调用其中的每个函数.然后用于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)