5

特定のインデックスで、「文字列」をベクトルに順次スライスする関数を書きたいと思います。私はそれにかなり適切なRソリューションを持っています。ただし、C/C++ でコードを記述した方が高速になる可能性が高いと思います。たとえば、次のように動作する関数「strslice」を記述できるようにしたいと考えています。

x <- "abcdef"
strslice( x, 2 ) ## should return c("ab", "cd", "ef")

ただし、Rcpp コードで渡された「CharacterVector」の要素を文字列として処理する方法がわかりません。これはうまくいくと私が想像するものです(C++/Rcppの知識が不足しているため、より良いアプローチがあると確信しています):

f <- rcpp( signature(x="character", n="integer"), '
  std::string myString = Rcpp::as<std::string>(x);
  int cutpoint = Rcpp::as<int>(n);
  vector<std::string> outString;
  int len = myString.length();
  for( int i=0; i<len/n; i=i+n ) {
    outString.push_back( myString.substr(i,i+n-1 ) );
    myString = myString.substr(i+n, len-i*n);
  }
  return Rcpp::wrap<Rcpp::CharacterVector>( outString );
  ')

記録のために、私が持っている対応する R コードは次のとおりです。

strslice <- function(x, n) {
  x <- as.data.frame( stringsAsFactors=FALSE, 
                      matrix( unlist( strsplit( x, "" ) ), ncol=n, byrow=T )
  )

  do.call( function(...) { paste(..., sep="") }, x )

}

...しかし、データ構造間を飛び回ると、非常に大きな文字列で処理が遅くなると思います。

(または、「strsplit」を強制的に動作させる方法はありますか?)

4

2 に答える 2

7

私は使用しますsubstring。このようなもの:

strslice <- function( x, n ){   
    starts <- seq( 1L, nchar(x), by = n )
    substring( x, starts, starts + n-1L )
}
strslice( "abcdef", 2 )
# [1] "ab" "cd" "ef"

コードについては、メモリ割り当てを意味するサイズ変更を避けるために、適切なサイズで をRcpp割り当てることができるかもしれません...または直接. このようなもの:std::vector<std::string>Rcpp::CharacterVector

strslice_rcpp <- rcpp( signature(x="character", n="integer"), '
    std::string myString = as<std::string>(x);
    int cutpoint = as<int>(n);
    int len = myString.length();
    int nout = len / cutpoint ;
    CharacterVector out( nout ) ;
    for( int i=0; i<nout; i++ ) {
      out[i] = myString.substr( cutpoint*i, 2 ) ;
    }
    return out ;
')
strslice_rcpp( "abdcefg", 2 )
# [1] "ab" "cd" "ef"
于 2012-11-10T08:00:03.807 に答える
4

gsubfnパッケージstrapplycから使用するこのワンライナーは十分に高速なので、rcpp は必要ないかもしれません。ここでは、数秒しかかからない James Joyce の Ulysses のテキスト全体に適用します。

library(gsubfn)
joyce <- readLines("http://www.gutenberg.org/files/4300/4300-8.txt") 
joycec <- paste(joyce, collapse = " ") # all in one string 
n <- 2
system.time(s <- strapplyc(joycec, paste(rep(".", n), collapse = ""))[[1]])
于 2012-11-10T16:16:58.077 に答える