2012-07-23 26 views

risposta

38

Ecco un modo

substring("aabbccccdd", seq(1, 9, 2), seq(2, 10, 2)) 
#[1] "aa" "bb" "cc" "cc" "dd" 

o più in generale

text <- "aabbccccdd" 
substring(text, seq(1, nchar(text)-1, 2), seq(2, nchar(text), 2)) 
#[1] "aa" "bb" "cc" "cc" "dd" 

Edit: Questo è molto, molto più veloce

sst <- strsplit(text, "")[[1]] 
out <- paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)]) 

E prima divide la stringa in caratteri. Quindi, incolla insieme gli elementi pari e gli elementi dispari.

Tempi

text <- paste(rep(paste0(letters, letters), 1000), collapse="") 
g1 <- function(text) { 
    substring(text, seq(1, nchar(text)-1, 2), seq(2, nchar(text), 2)) 
} 
g2 <- function(text) { 
    sst <- strsplit(text, "")[[1]] 
    paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)]) 
} 
identical(g1(text), g2(text)) 
#[1] TRUE 
library(rbenchmark) 
benchmark(g1=g1(text), g2=g2(text)) 
# test replications elapsed relative user.self sys.self user.child sys.child 
#1 g1   100 95.451 79.87531 95.438  0   0   0 
#2 g2   100 1.195 1.00000  1.196  0   0   0 
+0

Interessante, non conoscevano 'substring'. Molto più bello dato che 'substr' non accetta argomenti vettoriali per inizio/fine. –

+2

geniale! la seconda versione è davvero molto veloce! – MadSeb

+0

Mi chiedevo se c'era qualcosa di simile che avrebbe diviso "aabbbcccccdd" in aa bbb ccccc dd Al momento uso grepexpr. – jackStinger

8
string <- "aabbccccdd" 
# total length of string 
num.chars <- nchar(string) 

# the indices where each substr will start 
starts <- seq(1,num.chars, by=2) 

# chop it up 
sapply(starts, function(ii) { 
    substr(string, ii, ii+1) 
}) 

che dà

[1] "aa" "bb" "cc" "cc" "dd" 
1

si può usare una matrice per raggruppare i personaggi:

s2 <- function(x) { 
    m <- matrix(strsplit(x, '')[[1]], nrow=2) 
    apply(m, 2, paste, collapse='') 
} 

s2('aabbccddeeff') 
## [1] "aa" "bb" "cc" "dd" "ee" "ff" 

Purtroppo, TH è pause per un ingresso di dispari lunghezza della stringa, dando un avvertimento:

s2('abc') 
## [1] "ab" "ca" 
## Warning message: 
## In matrix(strsplit(x, "")[[1]], nrow = 2) : 
## data length [3] is not a sub-multiple or multiple of the number of rows [2] 

più spiacevole è che g1 e g2 da @GSee silenzio restituire risultati non corretti per un ingresso di dispari lunghezza della stringa:

g1('abc') 
## [1] "ab" 

g2('abc') 
## [1] "ab" "cb" 

Ecco la funzione nello spirito di s2, prendendo un parametro per il numero di caratteri in ciascun gruppo, e lascia l'ultima voce breve, se necessario:

s <- function(x, n) { 
    sst <- strsplit(x, '')[[1]] 
    m <- matrix('', nrow=n, ncol=(length(sst)+n-1)%/%n) 
    m[seq_along(sst)] <- sst 
    apply(m, 2, paste, collapse='') 
} 

s('hello world', 2) 
## [1] "he" "ll" "o " "wo" "rl" "d" 
s('hello world', 3) 
## [1] "hel" "lo " "wor" "ld" 

(E 'infatti più lento di g2, ma più veloce g1 di circa un fattore di 7)

+0

Se è possibile avere un numero dispari di caratteri, allora mi sembra che sarebbe più veloce gestirlo dopo il fatto che introdurre un ciclo 'apply'. Scommetto che è più veloce: 'out <- g2 (x); if (nchar (x) %% 2 == 1L) out [length (out)] <- substring (out [length (out)], 1, 1); esterno ne – GSee

1

brutto ma funziona

sequenceString <- "ATGAATAAAG" 

J=3#maximum sequence length in file 
sequenceSmallVecStart <- 
    substring(sequenceString, seq(1, nchar(sequenceString)-J+1, J), 
    seq(J,nchar(sequenceString), J)) 
sequenceSmallVecEnd <- 
    substring(sequenceString, max(seq(J, nchar(sequenceString), J))+1) 
sequenceSmallVec <- 
    c(sequenceSmallVecStart,sequenceSmallVecEnd) 
cat(sequenceSmallVec,sep = "\n") 

Dà ATG AAT AAA G

5

ci sono due facili possibilità:

s <- "aabbccccdd" 
  1. gregexpr e regmatches:

    regmatches(s, gregexpr(".{2}", s))[[1]] 
    # [1] "aa" "bb" "cc" "cc" "dd" 
    
  2. strsplit:

    strsplit(s, "(?<=.{2})", perl = TRUE)[[1]] 
    # [1] "aa" "bb" "cc" "cc" "dd" 
    
Problemi correlati