Ho una stringa come:Come suddividere una stringa in sottostringhe di una determinata lunghezza?
"aabbccccdd"
voglio rompere questa stringa in un vettore di stringhe di lunghezza 2:
"aa" "bb" "cc" "cc" "dd"
Ho una stringa come:Come suddividere una stringa in sottostringhe di una determinata lunghezza?
"aabbccccdd"
voglio rompere questa stringa in un vettore di stringhe di lunghezza 2:
"aa" "bb" "cc" "cc" "dd"
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
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"
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)
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
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
ci sono due facili possibilità:
s <- "aabbccccdd"
gregexpr
e regmatches
:
regmatches(s, gregexpr(".{2}", s))[[1]]
# [1] "aa" "bb" "cc" "cc" "dd"
strsplit
:
strsplit(s, "(?<=.{2})", perl = TRUE)[[1]]
# [1] "aa" "bb" "cc" "cc" "dd"
Interessante, non conoscevano 'substring'. Molto più bello dato che 'substr' non accetta argomenti vettoriali per inizio/fine. –
geniale! la seconda versione è davvero molto veloce! – MadSeb
Mi chiedevo se c'era qualcosa di simile che avrebbe diviso "aabbbcccccdd" in aa bbb ccccc dd Al momento uso grepexpr. – jackStinger