我是一个相对绿色的Rcpp用户,我不确定如何测试两个值是否相同。
例如,以下函数用于测试列表中是否包含值,但是对于简单测试用例返回的结果不正确
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
LogicalVector is_member (SEXP val, List coll) {
int coll_len = coll.size();
if (coll_len == 0) {
return LogicalVector::create();
} else {
Function identical("identical");
for (int ith = 0; ith < coll_len; ++ith) {
SEXP elem = coll[ith];
if (identical(val, elem)) {
return true;
}
}
return false;
}
}
is_member(1L, list(1L))
# FALSE
is_member(NaN, list(NaN, NaN))
# False
为什么会这样,以及如何使用相同的极端情况和基本功能“相同”的持久性来测试身份?我找不到任何Rcpp糖用于此目的,但是如果我找不到直接解决方案,我怀疑无序集或者可能使用唯一函数来测试身份。
如果我的C ++是非惯用的/危险的,我也会感激反馈,如果我一直含糊不清,请在下面留言,我会修改我的问题。
由于
答案 0 :(得分:5)
bool
转换为LogicalVector
。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
LogicalVector return_true() {
return true;
}
/*** R
return_true()
*/
给出
> return_true()
[1] FALSE
所以也许现在只返回LogicalVector::create(true)
?
代码中的另一个重大问题:identical
会返回SEXP
,而不是bool
!您希望明确地将结果作为bool
:
Shield<SEXP> result(identical(val, elem));
if (LOGICAL(result)[0]) { ... }
虽然直接将结果分配给bool
应该有效,但似乎它可能没有。当回到R时,仍有这样的陷阱。
那就是对你的代码的其他评论:
SEXP
。在这里你很幸运,因为List
的孩子受到了隐性保护,但总的来说这是不安全的。i
,这是最常见的格式(看到ith
会觉得奇怪)。事实证明,identical
也有一个C API。在RInternals.h
,我们有
/* R_compute_identical: C version of identical() function
The third arg to R_compute_identical() consists of bitmapped flags for non-default options:
currently all default to TRUE, so the flag is set for FALSE values:
1 = !NUM_EQ
2 = !SINGLE_NA
4 = !ATTR_AS_SET
8 = !IGNORE_BYTECODE
*/
Rboolean R_compute_identical(SEXP, SEXP, int);
因此您可能只想使用它。