Проверьте, находятся ли символы в строке

Я пытаюсь определить, является ли строка подмножеством другой строки. Например:

<code>chars <- "test"
value <- "es"
</code>

Я хочу вернуть значение ИСТИНА, если & quot; значение & quot; отображается как часть строки "chars". В следующем сценарии я хотел бы вернуть false:

<code>chars <- "test"
value <- "et"
</code>
 Joshua Cheek01 февр. 2017 г., 12:49
Принятый ответ неверен, нужно добавитьfixed=TRUEв противном случае вы воспринимаете это как регулярное выражение вместо строки. Смотрите мой ответ с октября 2016 года.

Ответы на вопрос(8)

Решение Вопроса

Использоватьgrepl функция

grepl(value, chars)
# TRUE
 11 мая 2017 г., 12:50
grepl (pattern, x) как минимум в 2017 году
 12 апр. 2012 г., 21:52
@Josh O 'brien, в этом посте сравнивалось нахождение (подсчет) всех совпадений в одной длинной строке, попробуйте найти 1 совпадение в связке более коротких строк:vec <- replicate(100000, paste( sample(letters, 10, replace=TRUE), collapse='') ).
 12 апр. 2012 г., 20:10
В этом простом случае добавление fixed = TRUE может повысить производительность (при условии, что вы будете выполнять много этих вычислений).
 25 апр. 2018 г., 01:20
Это не должен быть принятый ответ, потому что значение будет интерпретироваться как шаблон регулярного выражения. fixed = TRUE следует всегда использовать, если только вы не знаете, что искомая строка не будет выглядеть как шаблон регулярного выражения. Ответ Джошуа Крик ниже имеет очень четкое объяснение этого и должен быть принятым ответом.
 12 апр. 2012 г., 23:15
@GregSnow - попробовалsystem.time(a <- grepl("abc", vec)) а такжеsystem.time(a <- grepl("abc", vec, fixed=TRUE)), а такжеfixed=TRUE все еще, если что-нибудь немного медленнее. Разница не заметна с этими короткими строками, ноfixed=TRUE кажется, не быстрее. Спасибо за то, что указали, что это на длинных строках, которыеfixed=TRUE принимает настоящий удар.
Answer

мне понадобилось 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
Interpretation

grep назван в честь исполняемого файла Linux, который сам по себе является аббревиатурой от & quot;GЛОБАЛЬНЫЕRРегулярнаяEXpressionPrint & quot ;, он будет читать строки ввода и затем печатать их, если они соответствуют аргументам, которые вы указали. & Quot; Глобальный & Quot; означает, что совпадение может произойти в любом месте строки ввода, я объясню "Регулярное выражение" ниже, но идея в том, что это более разумный способ сопоставления строки (R называет этот «символ», например,class("abc")) и & quot; Печать & quot; поскольку он является программой командной строки, то вывод данных означает, что он печатает в свою строку вывода.

Теперьgrep Программа в основном представляет собой фильтр от строк ввода до строк вывода. И кажется, что R 'sgrep Функция аналогично будет принимать массив входов. По причинам, которые мне совершенно неизвестны (я начал играть с R около часа назад), он возвращает вектор совпадающих индексов, а не список совпадений.

Но, возвращаясь к вашему первоначальному вопросу, мы действительно хотим узнать, нашли ли мы иголку в стоге сена, истинное / ложное значение. По-видимому, они решили назвать эту функциюgreplкак в "grep" но с & quot;Logical & Quot; возвращаемое значение (они вызывают истинные и ложные логические значения, например,class(TRUE)).

Итак, теперь мы знаем, откуда пришло это имя и что оно должно делать. Вернемся к регулярным выражениям. Аргументы, даже если они являются строками, они используются для построения регулярных выражений (далее: regex). Регулярное выражение - это способ сопоставления строки (если это определение вас раздражает, отпустите его). Например, регулярное выражениеa соответствует персонажу"a"Регулярное выражениеa* соответствует персонажу"a" 0 или более раз, и регулярное выражениеa+ будет соответствовать характеру"a" 1 или более раз. Следовательно, в приведенном выше примере игла, которую мы ищем1+2, когда рассматривается как регулярное выражение, означает «один или более 1, а затем 2», но за нашим следует плюс!

1+2 as a regex

Итак, если вы использовалиgrepl без настройкиfixedваши иглы будут случайно стогами сена, и это будет работать довольно часто, мы можем видеть, что это даже работает на примере OP. Но это скрытая ошибка! Нам нужно сказать, что вход является строкой, а не регулярным выражением, что, по-видимому,fixed для. Почему исправлено? Понятия не имею, добавьте в закладки этот ответ, потому что вам, вероятно, придется искать его еще 5 раз, прежде чем вы его запомните.

A few final thoughts

Чем лучше ваш код, тем меньше истории вы должны знать, чтобы понять его. Каждый аргумент может иметь по меньшей мере два интересных значения (в противном случае он не должен быть аргументом), в этом документе перечислены 9 аргументов, что означает, что существует по меньшей мере 2 ^ 9 = 512 способов его вызова, что очень много. работы по написанию, тестированию и запоминанию ... отделите такие функции (разделите их, удалите зависимости друг от друга, строковые элементы отличаются от регулярных выражений, а не от векторных). Некоторые из этих опций также являются взаимоисключающими, не дают пользователям неправильных способов использования кода, то есть проблемный вызов должен быть структурно бессмысленным (например, передавая опцию, которая не существует), а не логически бессмысленным (где вы должны это сделать). выдать предупреждение, чтобы объяснить это). Выражаясь метафорически: заменять входную дверь на 10-м этаже стеной лучше, чем вывешивать табличку, предупреждающую против ее использования, но лучше либо ни того, ни другого. В интерфейсе функция определяет, как должны выглядеть аргументы, а не вызывающая сторона (поскольку вызывающая сторона зависит от функции, вывод всего того, с чем каждый может захотеть вызвать ее, делает функцию зависимой и от вызывающей стороны, и от этого типа циклическая зависимость быстро забьет систему и никогда не даст ожидаемых результатов). Будьте очень осторожны с двусмысленными типами, это недостаток дизайна, которыйTRUE а также0 а также"abc" все векторы.

 21 дек. 2017 г., 21:56
& Quot; фиксированный & Quot; относится к символам, соответствующим «фиксированному» последовательность.
 25 апр. 2017 г., 01:06
Приветствия за ваше объяснение! Кажется, что R эволюционировал в течение длительного периода времени и застрял с некоторыми странными проектными решениями (см., Например, ответы наthis question on value types). Однако возвращение вектора индексов совпадения в этом случае представляется целесообразным, так какgrep фильтрует строки, а не ячейки.

grep или жеgrepl but be aware of whether or not you want to use regular expressions.

По умолчанию,grep и связанные взятьregular expression чтобы соответствовать, не буквальная подстрока. Если вы этого не ожидаете и пытаетесь сопоставить недопустимое регулярное выражение, это не сработает:

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

Чтобы сделать настоящий тест подстроки, используйтеfixed = TRUE.

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

Если вы хотите регулярное выражение, отлично, но это не то, о чем спрашивает OP.

using "stringr" library:

> 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

если вы также хотите проверить, содержит ли строка (или набор строк) несколько подстрок, вы также можете использовать & apos; | & apos; между двумя подстроками.

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

Ты получишь

[1]  TRUE FALSE FALSE  TRUE

поскольку первое слово имеет подстроку "as", а последнее слово содержит подстроку "at"

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

grepl:

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

grep

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

Ваш ответ на вопрос