在R语言中组合逻辑函数:构建pass_tests多测试验证函数
这事儿好办!我帮你写一个灵活好用的pass_tests函数,既能整合多个测试的结果,还能按需返回不同格式的汇总信息。
实现
pass_tests函数的思路与代码 首先,我们的目标是让这个函数能接受任意多个测试函数(每个函数输入单个元素,返回TRUE/FALSE),对输入对象x的每个元素批量执行测试,最后把结果整理成易读的格式。
基础版函数实现
pass_tests <- function(x, ...) { # 收集所有传入的测试函数 tests <- list(...) # 边界检查:至少要传一个测试函数 if (length(tests) == 0) { stop("请至少传入一个测试函数!") } # 给测试函数命名:用户没命名的话自动生成 test_names <- names(tests) if (is.null(test_names)) { test_names <- paste0("test_", seq_along(tests)) } # 对x的每个元素,运行所有测试 results <- lapply(x, function(element) { sapply(tests, function(test) test(element)) }) # 把结果转换成数据框,设置行列名提升可读性 results_df <- do.call(rbind, results) rownames(results_df) <- names(x) %||% seq_along(x) colnames(results_df) <- test_names return(results_df) }
代码解释
- 收集测试函数:用
list(...)接收用户传入的任意多个测试函数,用法非常直观,比如pass_tests(x, test1, test2)。 - 命名处理:如果用户给测试函数指定了名字(比如
pass_tests(x, is_num = is.numeric)),就用用户的命名;否则自动生成test_1、test_2这类默认名。 - 批量执行测试:用
lapply遍历x的每个元素,对每个元素用sapply运行所有测试,得到该元素的所有测试结果。 - 结果整理:把分散的测试结果列表转换成数据框,行对应
x的元素(保留原命名或用序号),列对应测试函数,一目了然。
示例用法
先定义几个测试函数:
# 测试是否为数值型 is_numeric <- function(x) is.numeric(x) # 测试是否大于0 is_positive <- function(x) x > 0 # 测试是否为偶数(仅对整数生效) is_even <- function(x) ifelse(is.integer(x), x %% 2 == 0, FALSE)
然后测试一个混合类型的列表:
x <- list(a = 5, b = "hello", c = -3, d = 4L) pass_tests(x, is_numeric, is_positive, is_even)
输出结果:
is_numeric is_positive is_even a TRUE TRUE FALSE b FALSE FALSE FALSE c TRUE FALSE FALSE d TRUE TRUE TRUE
扩展版:支持不同汇总格式
如果需要更简洁的结果,可以给函数加个summary参数,支持返回通过测试的数量,或者是否通过所有测试:
pass_tests <- function(x, ..., summary = c("full", "pass_count", "all_passed")) { summary <- match.arg(summary) tests <- list(...) if (length(tests) == 0) { stop("请至少传入一个测试函数!") } test_names <- names(tests) %||% paste0("test_", seq_along(tests)) results <- lapply(x, function(element) { sapply(tests, function(test) test(element)) }) results_df <- do.call(rbind, results) rownames(results_df) <- names(x) %||% seq_along(x) colnames(results_df) <- test_names # 根据summary参数返回不同格式 switch(summary, "full" = results_df, "pass_count" = data.frame(pass_count = rowSums(results_df)), "all_passed" = data.frame(all_passed = apply(results_df, 1, all)) ) }
扩展版示例
# 返回每个元素通过的测试数量 pass_tests(x, is_numeric, is_positive, is_even, summary = "pass_count") # 返回是否通过所有测试 pass_tests(x, is_numeric, is_positive, is_even, summary = "all_passed")
输出分别是:
pass_count a 2 b 0 c 1 d 3
和
all_passed a FALSE b FALSE c FALSE d TRUE
注意事项
- 所有测试函数必须接受单个参数,并且返回
TRUE或FALSE。 - 不管
x是列表还是向量,lapply都能正常处理(向量会被拆分成单个元素的列表)。
内容的提问来源于stack exchange,提问作者ebeneditos
相关产品推荐
相关产品推荐

