Ответ 1
Используйте функцию grepl
grepl(value, chars)
# TRUE
Я пытаюсь определить, является ли строка подмножеством другой строки. Например:
chars <- "test"
value <- "es"
Я хочу вернуть TRUE, если "значение" появляется как часть строки "chars". В следующем сценарии я хотел бы вернуть false:
chars <- "test"
value <- "et"
Используйте функцию grepl
grepl(value, chars)
# 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
назван в честь исполняемого файла linux, который сам по себе является аббревиатурой " G lobal R egular E xpression P rint", он будет читать строки ввода, а затем распечатать их, если они соответствуют аргументам, которые вы дали. "Глобальный" означает, что совпадение может происходить в любом месте строки ввода, я объясню "Регулярное выражение" ниже, но идея заключается в более разумном способе сопоставления строки (R вызывает этот "символ", например class("abc")
), и "Печать", потому что это программа командной строки, испускающая выход, означает, что она печатает в свою выходную строку.
Теперь программа grep
представляет собой в основном фильтр, от строк ввода, до строк вывода. И похоже, что функция R grep
аналогичным образом будет принимать множество входов. По причинам, которые мне совершенно неизвестны (я только начал играть с R около часа назад), он возвращает вектор совпадающих индексов, а не список совпадений.
Но, вернемся к вашему первоначальному вопросу, мы действительно хотим знать, нашли ли мы иглу в стоге сена, истинное/ложное значение. По-видимому, они решили назвать эту функцию grepl
, как в "grep", но с возвратным значением " L ogical" (они вызывают истинные и ложные логические значения, например class(TRUE)
).
Итак, теперь мы знаем, откуда взялось имя и что он должен делать. Вернемся к регулярным выражениям. Аргументы, даже если они являются строками, используются для создания регулярных выражений (далее - регулярное выражение). Регулярное выражение - способ сопоставления строки (если это определение вас раздражает, пусть оно идет). Например, регулярное выражение a
соответствует символу "a"
, regex a*
соответствует символу "a"
0 или более раз, а regex a+
будет соответствовать символу "a"
1 или более раз. Следовательно, в приведенном выше примере игла, которую мы ищем 1+2
, когда она рассматривается как регулярное выражение, означает "один или несколько 1, за которым следует 2"... но за нами следует плюс!
Итак, если вы использовали grepl
без установки fixed
, ваши иглы случайно были бы стогами сена, и это бы часто работало довольно часто, мы можем видеть, что это даже работает для примера OP. Но это латентная ошибка! Нам нужно сказать, что ввод представляет собой строку, а не регулярное выражение, что, по-видимому, для fixed
. Почему исправлено? Нет подсказки, запишите этот ответ b/c, вам, вероятно, придется искать его еще 5 раз, прежде чем вы его запомните.
Чем лучше ваш код, тем меньше истории вы должны знать, чтобы понять это. Каждый аргумент может иметь как минимум два интересных значения (в противном случае это не обязательно должен быть аргумент), здесь приведен список аргументов 9-го документа, что означает, что существует не менее 2 ^ 9 = 512 способов его вызова, что большая работа пишите, проверяйте и помните... отделяйте такие функции (разделяйте их, удаляйте зависимости друг от друга, строки имеют разные значения, чем регулярные выражения, отличные от векторных вещей). Некоторые из опций также являются взаимоисключающими, не дают пользователям неправильных способов использования кода, то есть проблемный вызов должен быть структурно бессмысленным (например, передавать опцию, которая не существует), а не логически бессмысленно (где вы должны выпустить предупреждение, чтобы объяснить это). Поместите метафорически: заменив переднюю дверь на стороне 10-го этажа стеной лучше, чем навешивать знак, предупреждающий о его использовании, но ни лучше, ни ничем. В интерфейсе функция определяет, как должны выглядеть аргументы, а не вызывающий (потому что вызывающий объект зависит от функции, вызывая все, что каждый может когда-либо хотеть вызвать на нем, заставляет функцию также зависеть от вызывающих, и этот тип циклической зависимости быстро забивают систему и никогда не будут обеспечивать ожидаемые преимущества). Будьте очень осторожны с двусмысленными типами, это дизайнерский недостаток, что все вещи, такие как TRUE
и 0
и "abc"
, являются всеми векторами.
Вы хотите grepl
:
> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE
Используйте эту функцию из пакета 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
На всякий случай вам также хотелось бы проверить, содержит ли строка (или набор строк) несколько подстрок, вы также можете использовать '|' между двумя подстроками.
>substring="as|at"
>string_vector=c("ass","ear","eye","heat")
>grepl(substring,string_vector)
Вы получите
[1] TRUE FALSE FALSE TRUE
поскольку 1-е слово имеет подстроку "как", а последнее слово содержит подстроку "at"
Вы можете использовать grep
grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)
Используйте grep
или grepl
, но помните, хотите ли вы использовать регулярные выражения.
По умолчанию grep
и связанные с ним принимают регулярное выражение для соответствия, а не литеральную подстроку. Если вы этого не ожидаете, и вы пытаетесь сопоставить недопустимое регулярное выражение, оно не работает:
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
Чтобы выполнить истинный тест подстроки, используйте fixed = TRUE
.
> grep("[", "abc[", fixed = TRUE)
[1] 1
Если вам действительно нужно регулярное выражение, отлично, но это не то, о чем OP спрашивает.
Также можно сделать с помощью библиотеки 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