문자열이 다른 문자열의 하위 집합인지 확인하려고합니다. 예를 들면 다음과 같습니다.
chars <- "test"
value <- "es"
"value"가 "chars"문자열의 일부로 나타나면 TRUE를 반환하고 싶습니다. 다음 시나리오에서는 false를 반환하려고합니다.
chars <- "test"
value <- "et"
fixed=TRUE
데이터를 조용하고 미묘하게 엉망으로 만드는 버그가 있습니다.
문자열이 다른 문자열의 하위 집합인지 확인하려고합니다. 예를 들면 다음과 같습니다.
chars <- "test"
value <- "es"
"value"가 "chars"문자열의 일부로 나타나면 TRUE를 반환하고 싶습니다. 다음 시나리오에서는 false를 반환하려고합니다.
chars <- "test"
value <- "et"
fixed=TRUE
데이터를 조용하고 미묘하게 엉망으로 만드는 버그가 있습니다.
답변:
grepl
기능을 사용하십시오
grepl(value, chars, fixed = TRUE)
# TRUE
?grepl
자세한 내용을 알아 보려면 사용하십시오 .
vec <- replicate(100000, paste( sample(letters, 10, replace=TRUE), collapse='') )
.
system.time(a <- grepl("abc", vec))
하고 system.time(a <- grepl("abc", vec, fixed=TRUE))
, 그리고 fixed=TRUE
만약 아무것도 약간 느린, 아직도있다. 이 짧은 줄에서는 그 차이가 눈에 띄지 않지만 fixed=TRUE
여전히 더 빠르지는 않습니다. 그러나 fixed=TRUE
실제 히트 를 취하는 긴 줄에 있다는 것을 지적 해 주셔서 감사합니다 .
이 간단한 질문에 대한 답을 찾는 데 45 분이 걸렸습니다. 정답은: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
grep
의 약어가 자체 인 리눅스 실행 파일의 이름을 따서 명명된다 " G lobal R egular E xpression P RINT"는 입력 라인을 읽고 그들이 당신이 준 인수를 일치하는 경우 다음을 인쇄 할 것이다. "Global"은 입력 행의 어느 곳에서나 일치가 발생할 수 있음을 의미합니다. 아래 "Regular Expression"에 대해 설명하지만 문자열 (R은이 "문자"라고 함 class("abc")
) 및 "Print "명령 줄 프로그램이기 때문에 출력을내는 것은 출력 문자열로 인쇄한다는 의미입니다.
이제 grep
프로그램은 기본적으로 입력 라인에서 출력 라인에 이르는 필터입니다. 그리고 R의 grep
함수도 마찬가지로 입력 배열을 취할 것으로 보입니다 . 나에게 전혀 알려지지 않은 이유 때문에 (약 1 시간 전에 R을 사용하기 시작한 것), 일치하는 목록이 아니라 일치하는 인덱스의 벡터를 반환합니다.
그러나 원래 질문으로 돌아가서, 우리가 정말로 원하는 것은 건초 더미에서 바늘을 찾았는지, 참 / 거짓 값인지 아는 것입니다. 그들은 분명히이 기능의 이름을하기로 결정했다 grepl
"GREP"같이하지만, "와, L ogical"반환 값 (그들은, 예를 진실과 거짓 논리 값을 호출 class(TRUE)
).
이제 우리는 그 이름이 어디에서 왔으며 무엇을해야하는지 알게되었습니다. 정규식으로 돌아갑니다. 인수는 문자열이지만 정규 표현식을 작성하는 데 사용됩니다 (이후 정규 표현식). 정규 표현식은 문자열을 일치시키는 방법입니다 (이 정의가 자극을 주면 그대로 두십시오). 예를 들어, 정규식 a
은 문자와 일치하고 "a"
정규식 a*
은 문자와 "a"
0 번 이상 a+
일치하며 정규식 은 문자와 "a"
1 번 이상 일치합니다 . 따라서 위의 예에서, 우리가 찾고있는 바늘 1+2
은 정규 표현식으로 취급 될 때 "하나 이상 1 뒤에 2"가있는 것을 의미하지만 우리 뒤에는 플러스가 있습니다!
따라서 grepl
without 설정 을 사용 하지 않으면 fixed
바늘이 실수로 건초 더미가되어 실수로 자주 작동하는 경우 OP의 예에서도 작동한다는 것을 알 수 있습니다. 그러나 그것은 잠복적인 버그입니다! 우리는 입력이 정규 표현식이 아닌 문자열이라는 것을 분명히해야 fixed
합니다. 왜 고정 되었습니까? 실마리는 없습니다.이 답변을 북마크에 추가하십시오. 암기하기 전에 5 번 더 찾아봐야 할 것입니다.
코드가 좋을수록 코드를 이해하기 위해 알아야 할 이력이 줄어 듭니다. 모든 인수는 적어도 두 가지 흥미로운 값을 가질 수 있습니다 (그렇지 않으면 인수가 될 필요는 없습니다). 문서는 9 개의 인수를 나열합니다.이를 호출하는 데 적어도 2 ^ 9 = 512 가지 방법이 있다는 것을 의미합니다. 쓰기, 테스트 및 기억 ... 이러한 기능을 분리합니다 (분할, 서로 의존성 제거, 문자열 사물이 정규식 사물과 벡터 사물과 다름) 옵션 중 일부는 상호 배타적이며, 코드를 사용하는 잘못된 방법을 사용자에게 제공하지 않습니다. 즉, 문제가있는 호출은 논리적으로 무의미하지 않고 (존재하지 않는 옵션을 전달하는 등) 구조적으로 무의미해야합니다. 설명하기 위해 경고를 보냅니다). 은유 적으로 넣어 : 10 층 측면의 전면 도어를 벽으로 교체하는 것은 사용에 대해 경고하는 표지판을 걸는 것보다 낫지 만 둘 중 하나보다 낫습니다. 인터페이스에서 함수는 호출자가 아닌 인수의 모양을 정의합니다 (호출자는 함수에 의존하기 때문에 모든 사람이 호출하고자하는 모든 것을 유추하여 함수도 호출자에 따라 달라집니다. 주기적 종속성은 시스템을 빠르게 방해하고 기대하는 이점을 제공하지 않습니다). 혼란스러운 유형에 매우주의하십시오. 그것은 디자인 결함입니다. 모든 사람이 호출하고자하는 모든 것을 유추하면 함수도 호출자에게 의존하게 되며이 유형의 주기적 종속성은 시스템을 빠르게 방해하고 기대하는 이점을 제공하지 않습니다). 혼란스러운 유형에 매우주의하십시오. 그것은 디자인 결함입니다. 모든 사람이 호출하고자하는 모든 것을 유추하면 함수도 호출자에게 의존하게 되며이 유형의 주기적 종속성은 시스템을 빠르게 방해하고 기대하는 이점을 제공하지 않습니다). 혼란스러운 유형에 매우주의하십시오. 그것은 디자인 결함입니다.TRUE
과 0
및 "abc"
모든 벡터이다.
stringi
패키지 에서이 기능을 사용하십시오 .
> stri_detect_fixed("test",c("et","es"))
[1] FALSE TRUE
일부 벤치 마크 :
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
사용 grep
또는 grepl
그러나 당신이 정규 표현식을 사용할지 여부를 인식 .
기본적으로 grep
관련 은 리터럴 하위 문자열이 아닌 일치 하는 정규식을 사용합니다 . 그것을 기대하지 않고 유효하지 않은 정규식과 일치하려고하면 작동하지 않습니다.
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
실제 부분 문자열 테스트를 수행하려면을 사용하십시오 fixed = TRUE
.
> grep("[", "abc[", fixed = TRUE)
[1] 1
정규식을 원한다면 훌륭하지만 OP가 묻는 것처럼 보이지는 않습니다.
비슷한 문제가 있습니다 : 문자열과 키워드 목록이 주어지면 문자열에 포함 된 키워드가 있는지 감지하십시오.
이 스레드 추천 제안 stringr
의 str_detect
와 grepl
. microbenchmark
패키지 의 벤치 마크는 다음과 같습니다 .
사용
map_keywords = c("once", "twice", "few")
t = "yes but only a few times"
mapper1 <- function (x) {
r = str_detect(x, map_keywords)
}
mapper2 <- function (x) {
r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}
그리고
microbenchmark(mapper1(t), mapper2(t), times = 5000)
우리는 찾는다
Unit: microseconds
expr min lq mean median uq max neval
mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476 5000
mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837 5000
당신이 볼 수 있듯이, 5000 이상 반복 사용하여 검색 키워드 str_detect
및 grepl
키워드의 실제 문자열 및 벡터 이상 grepl
꽤보다 더 잘 수행 str_detect
.
결과는 r
어떤 키워드가 문자열에 포함되어 있는지 식별하는 부울 벡터 입니다.
따라서 grepl
키워드가 문자열인지 확인하는 데 사용 하는 것이 좋습니다 .
fixed=TRUE
. 그렇지 않으면 문자열 대신 정규식으로 처리합니다. 2016 년 10 월에서 내 답변을 참조하십시오.