Noté que la función única de Rcpp ordena los resultados

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

Hay alguna manera de evitar esto ? Gracias por tu ayuda

0
user3507085 22 jun. 2017 a las 14:04

3 respuestas

La mejor respuesta

Si observa el archivo fuente (corto) verá que usa una clase interna IndexHash. Sospecho que este se ordena por defecto.

Si el pedido original es primordial, supuse que podría escribir un nuevo envoltorio de conveniencia. No puede ser tan difícil: a riesgo de desperdiciar unos pocos bytes de memoria, asigne un vector lógico temporal, use un hashmap estándar y realice un bucle sobre el vector entrante. Para cada valor, pregunte si el hashmap ha visto este valor, almacene la respuesta booleana. Luego use eso para indexar el vector original.

Lo más probable es que esto se implemente en alguna parte. También mire a Armadillo y Eigen para las funciones de utilidad.

1
SymbolixAU 9 ene. 2020 a las 21:55

Esto podría ayudar a alguien: funciona solo para vectores ordenados.

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


0
GoGonzo 18 dic. 2019 a las 03:57

Así es como lo implementé, junto con el problema que estaba tratando de resolver cuando se me ocurrió (usando esta respuesta, y también muestra varias otras soluciones y puntos de referencia).

  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;
  }
0
SymbolixAU 12 ene. 2020 a las 20:56