Abbinamento di più modelli

Voglio vedere, se "001" o "100" o "000" verificano in una stringa di 4 caratteri di 0 e 1 . Ad esempio, una stringa di 4 caratteri potrebbe essere come "1100" o "0010" o "1001" o "1111" . Come faccio a far corrispondere molte stringhe in una stringa con un singolo comando?

So che grep potrebbe essere usato per la corrispondenza dei pattern, ma usando grep, posso controllare solo una stringa alla volta. Voglio sapere se più stringhe possono essere usate con qualche altro comando o con grep stesso.

Si, puoi. Il | in un modello di grep ha lo stesso significato di or . Quindi puoi testare il tuo pattern usando "001|100|000" come pattern. Allo stesso tempo, grep è vettorizzato, quindi tutto questo può essere fatto in un solo passaggio:

 x <- c("1100", "0010", "1001", "1111") pattern <- "001|100|000" grep(pattern, x) [1] 1 2 3 

Questo restituisce un indice di quale dei tuoi vettori conteneva il modello di corrispondenza (in questo caso i primi tre).

A volte è più conveniente avere un vettore logico che ti indichi quali elementi del tuo vettore sono stati abbinati. Quindi puoi usare grepl :

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

Vedi ?regex per aiuto sulle espressioni regolari in R.


Modifica: per evitare di creare pattern manualmente, possiamo usare paste :

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

Ecco una soluzione che utilizza il pacchetto stringr

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

Usa l’argomento -e per aggiungere altri pattern:

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

Puoi anche usare l’operatore %like% dalla libreria 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 si desidera il vettore logico, è necessario verificare la funzione stringi dal pacchetto stringi . Nel tuo caso il pattern è regex, quindi usa questo:

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

E alcuni punti di riferimento:

 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 

Ci scusiamo per aver reso questa risposta addizionale, ma sono troppe le righe per un commento.

Volevo solo ricordare che il numero di elementi che possono essere incollati insieme tramite paste(..., collapse = "|") da utilizzare come un unico pattern di corrispondenza è limitato – vedi sotto. Forse qualcuno può dire dove è esattamente il limite? Certo, il numero potrebbe non essere realistico, ma a seconda del compito da svolgere non dovrebbe essere completamente escluso dalle nostre considerazioni.

Per un numero molto elevato di articoli, sarebbe necessario un ciclo per controllare ogni elemento del modello.

 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)