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

strapplycgsubfn包中使用的这一单行程序足够快,可能不需要 rcpp。在这里,我们将其应用于詹姆斯乔伊斯的《尤利西斯》的整个文本,只需要几秒钟:

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 回答