2012-11-10 21 views
5

मैं एक ऐसा फ़ंक्शन लिखना चाहता हूं जो किसी दिए गए इंडेक्स पर अनुक्रमिक रूप से एक वेक्टर में 'स्ट्रिंग' स्लाइस करता है। मेरे पास इसके लिए पर्याप्त पर्याप्त समाधान है; हालांकि, मुझे लगता है कि सी/सी ++ में कोड लिखना शायद तेज होगा। उदाहरण के लिए, मैं इस प्रकार एक समारोह 'strslice' है कि संचालित लिखने में सक्षम होना चाहते हैं:आर/आरसीपीपी के साथ लगातार सूचकांक पर एक स्ट्रिंग स्लाइस?

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

हालांकि, मैं कैसे 'CharacterVector' में चारों ओर से पारित कर दिया की इलाज के तत्वों को संभालने के लिए यकीन नहीं है स्ट्रिंग के रूप में आरसीपीपी कोड। यह मैं क्या सोच भी काम कर सकते हैं (सी ++/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); 
    ') 

रिकॉर्ड के लिए, इसी आर कोड रहा है:

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

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

} 

... लेकिन मैं डेटा संरचनाओं के बीच चारों ओर कूदते हुए बहुत अधिक तारों के साथ चीजों को धीमा कर दूंगा।

:

+0

आपको शायद बायोस्टर्स पैकेज को देखना चाहिए। –

उत्तर

7

मैं substring का प्रयोग करेंगे (वैकल्पिक रूप से वहाँ से व्यवहार के रूप में मैं चाहता हूँ में 'strsplit' मजबूर करने के लिए एक रास्ता है?)। कुछ इस तरह:

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

कि आरसीपीपी समाधान तेजी से चमक रहा है। धन्यवाद! –

4

यह एक लाइनर gsubfn पैकेज से strapplyc का उपयोग कर काफी तेजी से कि 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]]) 
संबंधित मुद्दे