Rcpp唯一订单输出

h43kikqp  于 2023-04-27  发布在  其他
关注(0)|答案(4)|浏览(92)

我注意到来自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

有办法避免这种情况吗?谢谢你的帮助

gstyhher

gstyhher1#

如果你看一下(短)源文件,你会发现它使用了一个内部类IndexHash
如果原始顺序是最重要的,我想你可以自己写一个新的方便 Package 。它不会这么难:冒着浪费几个字节内存的风险,分配一个临时的逻辑向量,使用一个标准的hashmap并在传入的向量上循环。对于每个值,询问hashmap是否已经看到这个值,存储布尔答案。然后使用它来索引原始向量。
很有可能这甚至在某个地方实现了。也可以看看Armadillo和Eigen的效用函数。

gpnt7bae

gpnt7bae2#

这就是我如何实现它的,沿着我在提出它时试图解决的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;
  }
zazmityj

zazmityj3#

这一个可能会帮助一些人-只适用于排序向量。

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;
  }
o4tp2gmn

o4tp2gmn4#

您可以使用duplicated(_) == 0来重复数据,同时保持第一次出现的顺序:

IntegerVector x = {6,6,1,5,5,1};
IntegerVector out = x[duplicated(x) == 0];
Rcout << out << std::endl;

相关问题