Combinando vários padrões

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) 
Intereting Posts