Rcpp唯一顺序输出

Rcpp unique order output

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

有没有办法避免这种情况? 感谢您的帮助

如果您查看(简短的)源文件,您会发现它使用了内部 class IndexHash。我怀疑这是默认排序。

如果原始顺序最重要,我想你可以自己写一个新的便利包装。它不可能这么难:冒着浪费几个字节内存的风险,分配一个临时逻辑向量,使用标准哈希图并循环传入的向量。对于每个值,询问 hashmap 是否已经看到这个值,存储布尔值答案。然后用它来索引原始向量。

有可能这甚至在某处实施。还可以查看 Armadillo 和 Eigen 的实用函数。

这个可能对某人有所帮助 - 仅适用于排序的向量。

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


这就是我实现它的方式,以及 issue I was trying to solve when I came up with it (using 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;
  }