2011-08-04 18 views
17

Quiero ver, si "001" o "100" o "000" se produce en una cadena de 4 caracteres de 0 y 1. Por ejemplo, una cadena de 4 caracteres podría ser como "1100" o "0010" o "1001" o "1111". ¿Cómo puedo unir muchas cadenas en una cadena con un solo comando?Coincidencia de una cadena con diferentes posibilidades usando grep

Sé que grep podría usarse para la coincidencia de patrones, pero al usar grep, puedo verificar solo una cadena a la vez. Quiero saber si se pueden usar varias cadenas con algún otro comando o con grep.

Respuesta

37

Sí, se puede. El | en un patrón grep tiene el mismo significado que or. Entonces puede probar su patrón usando "001|100|000" como patrón. Al mismo tiempo, grep se vectorizado, por lo que todo esto se puede hacer en un solo paso: (. En este caso el primero de tres)

x <- c("1100", "0010", "1001", "1111") 
pattern <- "001|100|000" 

grep(pattern, x) 
[1] 1 2 3 

Esto devuelve un índice de cuál de sus vectores contenía el patrón coincidente

A veces es más conveniente tener un vector lógico que le indique cuáles de los elementos de su vector coinciden. A continuación, puede utilizar grepl:

grepl(pattern, x) 
[1] TRUE TRUE TRUE FALSE 

Ver ?regex ayuda acerca de las expresiones regulares en R.


Editar: Para evitar la creación de patrones manualmente podemos utilizar paste:

myValues <- c("001", "100", "000") 
pattern <- paste(myValues, collapse = "|") 
+0

@andrie, esto absolutamente brillante, suponía que es imposible durante años, mientras que es simplemente una expresión regular,

+4

@DavidArenburg :-) He aprendido de la amarga experiencia que nada es imposible en R. Siempre es solo una cuestión de ¡cómo! – Andrie

2

Utilice el argumento -e para añadir patrones adicionales:

echo '1100' | grep -e '001' -e '110' -e '101' 
+2

Lo siento, pero olvidé mencionar que quiero hacer esto en R. – Narayani

+0

esto es útil de todos modos. – marbel

6

Aquí hay una solución usando stringr paquete

require(stringr) 
mylist = c("1100", "0010", "1001", "1111") 
str_locate(mylist, "000|001|100") 
1

También puede utilizar el operador de %like%data.table biblioteca.

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 
+0

Tenga en cuenta que '% like%' es solo un contenedor para 'grepl', check'?% Like% '" Argumentos: ... \t patrón \t Pasado a grepl. ". Al menos hasta 'data.table' version 1.10.4-2. –

1

Si quieren vector lógico entonces usted debe comprobar stri_detect función de stringi paquete. En su caso, el patrón es de expresiones regulares, a fin de utilizar esta:

stri_detect_regex(x, pattern) 
## [1] TRUE TRUE TRUE FALSE 

Y algunos puntos de referencia:

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 
0

Lo siento por hacer esto una respuesta additonal, pero es demasiado muchas líneas de comentario.

Solo quería recordar que el número de elementos que se pueden pegar juntos a través de paste(..., collapse = "|") para usarse como un único patrón coincidente es limitado - vea debajo. ¿Tal vez alguien puede decir dónde está exactamente el límite? Es cierto que el número podría no ser realista, pero, dependiendo de la tarea a realizar, no debería excluirse por completo de nuestras consideraciones.

Para una cantidad realmente grande de elementos, se requerirá un bucle para verificar cada elemento del patrón.

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) 
Cuestiones relacionadas