una separar palabra manejo funcion comodines comando caracteres cadenas cadena buscar r regex string r-faq

separar - Probar si los caracteres están en una cadena



manejo de cadenas en r (8)

Estoy tratando de determinar si una cadena es un subconjunto de otra cadena. Por ejemplo:

chars <- "test" value <- "es"

Quiero devolver VERDADERO si "valor" aparece como parte de la cadena "caracteres". En el siguiente escenario, me gustaría devolver falso:

chars <- "test" value <- "et"


Responder

Suspiro, me tomó 45 minutos encontrar la respuesta a esta simple pregunta. La respuesta es: grepl(needle, haystack, fixed=TRUE)

# Correct > grepl("1+2", "1+2", fixed=TRUE) [1] TRUE > grepl("1+2", "123+456", fixed=TRUE) [1] FALSE # Incorrect > grepl("1+2", "1+2") [1] FALSE > grepl("1+2", "123+456") [1] TRUE

Interpretación

grep lleva el nombre del ejecutable de Linux, que es en sí mismo un acrónimo de " G lobal R egular E xpression P rint", leerá las líneas de entrada y luego las imprimirá si coinciden con los argumentos proporcionados. "Global" significa que la coincidencia podría ocurrir en cualquier lugar de la línea de entrada, explicaré la "Expresión regular" a continuación, pero la idea es que es una forma más inteligente de hacer coincidir la cadena (R llama a este "carácter", por ejemplo, class("abc") ), e "Imprimir" porque es un programa de línea de comandos, emitir salida significa que se imprime en su cadena de salida.

Ahora, el programa grep es básicamente un filtro, desde líneas de entrada hasta líneas de salida. Y parece que la función grep de R de manera similar tomará una serie de entradas. Por razones que me son completamente desconocidas (solo empecé a jugar con R hace aproximadamente una hora), devuelve un vector de los índices que coinciden, en lugar de una lista de coincidencias.

Pero, volviendo a su pregunta original, lo que realmente queremos es saber si encontramos la aguja en el pajar, un valor verdadero / falso. Aparentemente, decidieron grepl a esta función grepl , como en "grep" pero con un valor de retorno "lógico" (llaman valores lógicos verdaderos y falsos, por ejemplo, class(TRUE) ).

Entonces, ahora sabemos de dónde viene el nombre y qué se supone que debe hacer. Regresemos a las expresiones regulares. Los argumentos, aunque son cadenas, se usan para construir expresiones regulares (en adelante, expresiones regulares). Una expresión regular es una forma de hacer coincidir una cadena (si esta definición lo irrita, déjelo ir). Por ejemplo, la expresión regular a coincide con el carácter "a" , la expresión regular a* coincide con el carácter "a" 0 veces o más, y la expresión regular a+ coincidirá con el carácter "a" una o más veces. Por lo tanto, en el ejemplo anterior, la aguja que estamos buscando para 1+2 , cuando se trata como una expresión regular, significa "uno o más 1 seguido de un 2" ... ¡pero a la nuestra le sigue un signo más!

Por lo tanto, si usó el grepl sin establecer el ajuste fixed , sus agujas serían pajares accidentalmente, y eso funcionaría accidentalmente con bastante frecuencia, podemos ver que incluso funciona para el ejemplo del OP. ¡Pero eso es un error latente! Necesitamos decirle que la entrada es una cadena, no una expresión regular, que aparentemente es para lo que se fixed . ¿Por qué arreglado? Sin pista, marque esta respuesta b / c probablemente tendrá que buscarla 5 veces más antes de memorizarla.

Algunos pensamientos finales

Cuanto mejor sea tu código, menos historia tendrás que conocer para que tenga sentido. Cada argumento puede tener al menos dos valores interesantes (de lo contrario no tendría que ser un argumento), los documentos enumeran 9 argumentos aquí, lo que significa que hay al menos 2 ^ 9 = 512 formas de invocarlo, eso es mucho trabajo para escriba, pruebe y recuerde ... desacople estas funciones (divídalos, elimine las dependencias entre sí, las cosas de cadena son diferentes a las de expresiones regulares y las cosas vectoriales). Algunas de las opciones también se excluyen mutuamente, no les da a los usuarios formas incorrectas de usar el código, es decir, la invocación problemática debe ser estructuralmente sin sentido (como pasar una opción que no existe), no lógicamente sin sentido (donde tiene que emitir una advertencia para explicarlo). Colóquese metafóricamente: reemplazar la puerta delantera en el costado del piso 10 con una pared es mejor que colgar un cartel que advierta sobre su uso, pero que cualquiera sea mejor que ninguno. En una interfaz, la función define el aspecto de los argumentos, no la persona que llama (ya que la persona que llama depende de la función, al inferir todo lo que todo el mundo pueda desear hacer) la función también depende de las personas que llaman, y este tipo La dependencia cíclica obstruirá rápidamente un sistema y nunca proporcionará los beneficios que espera). Tenga mucho cuidado con los tipos equívocos, es un defecto de diseño que cosas como TRUE y 0 y "abc" son todos vectores.


En caso de que también desee comprobar si una cadena (o un conjunto de cadenas) contiene varias cadenas secundarias, también puede usar la tecla ''|'' entre dos subcadenas.

>substring="as|at" >string_vector=c("ass","ear","eye","heat") >grepl(substring,string_vector)

Conseguirás

[1] TRUE FALSE FALSE TRUE

ya que la primera palabra tiene subcadena "como", y la última palabra contiene subcadena "en"


Puedes usar grep

grep("es", "Test") [1] 1 grep("et", "Test") integer(0)


Quieres grepl

> chars <- "test" > value <- "es" > grepl(value, chars) [1] TRUE > chars <- "test" > value <- "et" > grepl(value, chars) [1] FALSE


También, se puede hacer usando la biblioteca "stringr":

> library(stringr) > chars <- "test" > value <- "es" > str_detect(chars, value) [1] TRUE ### For multiple value case: > value <- c("es", "l", "est", "a", "test") > str_detect(chars, value) [1] TRUE FALSE TRUE FALSE TRUE


Usa la función grepl .

grepl(value, chars) # TRUE


Use grep o grepl pero tenga en cuenta si desea o no usar expresiones regulares .

Por defecto, grep y related toman una expresión regular para coincidir, no una subcadena literal. Si no estás esperando eso, e intentas hacer coincidir en una expresión regular no válida, no funciona:

> grep("[", "abc[") Error in grep("[", "abc[") : invalid regular expression ''['', reason ''Missing '']''''

Para hacer una prueba de subcadena verdadera, use fixed = TRUE .

> grep("[", "abc[", fixed = TRUE) [1] 1

Si quiere expresiones regulares, genial, pero eso no es lo que el OP parece estar preguntando.


Utilice esta función del paquete stringi :

> stri_detect_fixed("test",c("et","es")) [1] FALSE TRUE

Algunos puntos de referencia:

library(stringi) set.seed(123L) value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings head(value) chars <- "es" library(microbenchmark) microbenchmark( grepl(chars, value), grepl(chars, value, fixed=TRUE), grepl(chars, value, perl=TRUE), stri_detect_fixed(value, chars), stri_detect_regex(value, chars) ) ## Unit: milliseconds ## expr min lq median uq max neval ## grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530 100 ## grepl(chars, value, fixed = TRUE) 5.071617 5.110779 5.281498 5.523421 45.243791 100 ## grepl(chars, value, perl = TRUE) 1.835558 1.873280 1.956974 2.259203 3.506741 100 ## stri_detect_fixed(value, chars) 1.191403 1.233287 1.309720 1.510677 2.821284 100 ## stri_detect_regex(value, chars) 6.043537 6.154198 6.273506 6.447714 7.884380 100