如何用R核心函数Reduce比较对象向量?all.equal为何失效
R语言用Reduce结合对象比较的解决方案
失效原因解释
==是基础比较运算符,仅返回逻辑值TRUE/FALSE,你的示例中刚好元素值为1,和R中逻辑值TRUE的底层存储数值相等,才侥幸得到正确结果,本身这个用法存在逻辑漏洞:如果测试向量为c(2,2,2),Reduce("==", c(2,2,2))会返回FALSE,不符合预期。all.equal的返回规则为:两个对比对象相等时返回逻辑值TRUE,不等时返回描述差异的字符向量。Reduce的运行逻辑是将上一次函数调用的返回值作为下一次调用的第一个输入参数,因此第一次比较前两个元素得到TRUE后,第二次会调用all.equal(TRUE, 第三个元素),两类对象类型不匹配,就会返回差异字符串,后续迭代进一步触发报错。
仅用R核心函数的实现方案
方案1:基准比较法(更简洁,推荐)
不需要依赖Reduce,取第一个元素作为基准,其余所有元素和基准对比即可适配任意对象类型:
# 通用函数:判断向量/列表中所有元素是否完全相等 all_equal <- function(x) { if (length(x) <= 1) return(TRUE) all(sapply(x[-1], function(item) isTRUE(all.equal(x[[1]], item)))) } # 数值向量测试 test <- c(1,1,1,1,1) all_equal(test) # 输出 [1] TRUE # 数据框对象测试 test_obj <- list(iris, iris, iris) all_equal(test_obj) # 输出 [1] TRUE
方案2:适配Reduce的实现
如果必须使用Reduce实现,可以包装all.equal使其符合Reduce的迭代规则:
# 适配Reduce迭代的比较包装函数 reduce_compare <- function(prev, curr) { # 前序迭代已经判定不等,直接返回FALSE if (is.logical(prev) && !prev) return(FALSE) # 相等返回当前对象作为下一轮迭代的基准,不等返回FALSE if (isTRUE(all.equal(prev, curr))) curr else FALSE } # 调用测试 test <- c(1,1,1,1,1) isTRUE(Reduce(reduce_compare, test)) # 输出 [1] TRUE test_obj <- list(data.frame(a=1:3, b=4:6), data.frame(a=1:3, b=4:6)) isTRUE(Reduce(reduce_compare, test_obj)) # 输出 [1] TRUE
内容的提问来源于stack exchange,提问作者scs
相关产品推荐
相关产品推荐

