我注意到Rcpp的独特功能命令结果
evalCpp("unique(IntegerVector::create(6,6,1,5,5,1))")
[1] 6 5 1
unique(c(6,6,1,5,5,1))
[1] 6 1 5
有没有办法避免这种情况? 谢谢你的帮助
答案 0 :(得分:1)
如果查看(简短)源文件,您会看到它使用内部类IndexHash
。我怀疑这个默认排序。
如果原始订单是最重要的,我想你可以自己写一个新的便利包装。它不是那么难:冒着浪费几个字节的内存的风险,分配一个临时的逻辑向量,使用标准的hashmap并在传入的向量上循环。对于每个值,询问hashmap是否已看到此值,存储布尔值答案。然后用它来索引原始矢量。
这已经在某处实现了。还可以查看Armadillo和Eigen的实用功能。
答案 1 :(得分:0)
这可能会帮助某人-仅适用于排序的向量。
template <int ITYPE>
Rcpp::Vector<ITYPE> unique(Rcpp::Vector<ITYPE> x) {
int n = x.size();
if (n == 1) return(x);
Rcpp::Vector<ITYPE> res;
res.push_back(x(0));
for (int i = 1; i < n; i++) {
if (x[i] != x(i - 1)) {
res.push_back(x(i));
}
}
return res;
}
答案 2 :(得分:0)
这就是我与issue一起尝试解决的问题的实现方式(使用this answer,并显示了其他各种解决方案和基准)。
template < typename T, int RTYPE >
inline SEXP sexp_unique( Rcpp::Vector< RTYPE > x ) {
std::set< T > seen;
auto newEnd = std::remove_if( x.begin(), x.end(), [&seen]( const T value ) {
if ( seen.find( value ) != std::end( seen ) ) {
return true;
}
seen.insert( value );
return false;
});
x.erase( newEnd, x.end() );
return x;
}
// returns unique values in their original input order
inline SEXP get_sexp_unique( SEXP s ) {
SEXP s2 = Rcpp::clone( s );
switch( TYPEOF( s2 ) ) {
case LGLSXP: {
return sexp_unique< bool, LGLSXP >( s2 );
}
case REALSXP: {
return sexp_unique< double, REALSXP >( s2 );
}
case INTSXP: {
return sexp_unique< int, INTSXP >( s2 );
}
case STRSXP: {
return sexp_unique< char* , STRSXP >( s2 );
}
default: Rcpp::stop("unknown vector type");
}
return 0;
}