2012-11-10 16 views
5

Chcę napisać funkcję, która wycina "ciąg" w wektorze, sekwencyjnie, w danym indeksie. Mam dla niego dość odpowiednie rozwiązanie R; jednak myślę, że napisanie kodu w C/C++ byłoby prawdopodobnie szybsze. Na przykład, chciałbym, aby móc napisać funkcję „strslice”, który działa w następujący sposób:Wyciąć łańcuch w kolejnych indeksach za pomocą R/Rcpp?

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

Jednak nie jestem pewien, jak obsługiwać traktując elementy „CharacterVector” przeszedł w okolice Kod Rcpp jako ciągi. To jest to, co ja sobie wyobrazić, może działać (biorąc pod uwagę mój brak C++/wiedzy RCPP Jestem pewien, że istnieje lepszy sposób):

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); 
    ') 

Dla przypomnienia, odpowiedni kod R mam to:

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

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

} 

... ale myślę, że przeskakiwanie pomiędzy strukturami danych tak bardzo spowalnia rzeczy z bardzo dużymi łańcuchami.

(alternatywnie: czy istnieje sposób, aby zmusić „strsplit” zachowuje się jak chcę?)

+0

Powinieneś prawdopodobnie spojrzeć na pakiet Biostrings. –

Odpowiedz

7

użyłbym substring. Coś takiego:

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

O kodzie Rcpp, może można przeznaczyć std::vector<std::string> z odpowiedniej wielkości, tak aby uniknąć jej rozmiaru, który może oznaczać alokacji pamięci, ... a może bezpośrednio użyć Rcpp::CharacterVector. Coś takiego:

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" 
+1

To rozwiązanie Rcpp jest szybkie. Dzięki! –

4

To jedna wkładka użyciu strapplyc z pakietu gsubfn jest wystarczająco szybki, nie mogą być potrzebne, że RCPP. Stosujemy go do całego tekstu Ulissesa Jamesa Joyce'a, który zajmuje tylko kilka sekund:

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]]) 
Powiązane problemy