Eu quero ver, se "001"
ou "100"
ou "000"
ocorre em uma seqüência de 4 caracteres de 0
e 1
. Por exemplo, uma cadeia de 4 caracteres pode ser como "1100"
ou "0010"
ou "1001"
ou "1111"
. Como faço para combinar muitas strings em uma string com um único comando?
Eu sei grep poderia ser usado para correspondência de padrões, mas usando o grep, eu posso verificar apenas uma seqüência de cada vez. Eu quero saber se várias strings podem ser usadas com algum outro comando ou com o próprio grep.
Sim você pode. O |
em um padrão grep
tem o mesmo significado que or
. Então você pode testar seu padrão usando "001|100|000"
como seu padrão. Ao mesmo tempo, o grep
é vetorizado, então tudo isso pode ser feito em uma única etapa:
x <- c("1100", "0010", "1001", "1111") pattern <- "001|100|000" grep(pattern, x) [1] 1 2 3
Isso retorna um índice de quais de seus vetores continham o padrão de correspondência (nesse caso, os três primeiros).
Às vezes, é mais conveniente ter um vetor lógico que informa quais elementos do seu vetor foram correspondidos. Então você pode usar grepl
:
grepl(pattern, x) [1] TRUE TRUE TRUE FALSE
Veja ?regex
para ajuda sobre expressões regulares em R.
Edit: Para evitar a criação de padrão manualmente, podemos usar paste
:
myValues <- c("001", "100", "000") pattern <- paste(myValues, collapse = "|")
Aqui está uma solução usando o pacote stringr
require(stringr) mylist = c("1100", "0010", "1001", "1111") str_locate(mylist, "000|001|100")
Use o argumento -e para include padrões adicionais:
echo '1100' | grep -e '001' -e '110' -e '101'
Você também pode usar o operador %like%
da biblioteca data.table
.
library(data.table) # input x <- c("1100", "0010", "1001", "1111") pattern <- "001|100|000" # check for pattern x %like% pattern > [1] TRUE TRUE TRUE FALSE
Se você quiser vetor lógico, então você deve verificar a function stringi
pacote stringi
. No seu caso, o padrão é regex, então use este:
stri_detect_regex(x, pattern) ## [1] TRUE TRUE TRUE FALSE
E alguns benchmarks:
require(microbenchmark) test <- stri_paste(stri_rand_strings(100000, 4, "[0-1]")) head(test) ## [1] "0001" "1111" "1101" "1101" "1110" "0110" microbenchmark(stri_detect_regex(test, pattern), grepl(pattern, test)) Unit: milliseconds expr min lq mean median uq max neval stri_detect_regex(test, pattern) 29.67405 30.30656 31.61175 30.93748 33.14948 35.90658 100 grepl(pattern, test) 36.72723 37.71329 40.08595 40.01104 41.57586 48.63421 100
Desculpe por fazer isso uma resposta adicional, mas é muitas linhas para um comentário.
Eu só queria lembrar, que o número de itens que podem ser colados juntos via paste(..., collapse = "|")
para ser usado como um único padrão de correspondência é limitado – veja abaixo. Talvez alguém possa dizer exatamente onde está o limite? É certo que o número pode não ser realista, mas dependendo da tarefa a ser executada, ele não deve ser inteiramente excluído de nossas considerações.
Para um número realmente grande de itens, seria necessário um loop para verificar cada item do padrão.
set.seed(0) samplefun <- function(n, x, collapse){ paste(sample(x, n, replace=TRUE), collapse=collapse) } words <- sapply(rpois(10000000, 8) + 1, samplefun, letters, '') text <- sapply(rpois(1000, 5) + 1, samplefun, words, ' ') #since execution takes a while, I have commented out the following lines #result <- grepl(paste(words, collapse = "|"), text) # Error in grepl(pattern, text) : # invalid regular expression # 'wljtpgjqtnw|twiv|jphmer|mcemahvlsjxr|grehqfgldkgfu| # ... #result <- stringi::stri_detect_regex(text, paste(words, collapse = "|")) # Error in stringi::stri_detect_regex(text, paste(words, collapse = "|")) : # Pattern exceeds limits on size or complexity. (U_REGEX_PATTERN_TOO_BIG)