Проверьте, если символы в строке в R

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

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

Я хочу вернуть TRUE, если "значение" появляется как часть строки "chars". В следующем сценарии я хотел бы вернуть false:

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

Ответ 1

Используйте функцию grepl

grepl(value, chars)
# TRUE

Ответ 2

Ответ

Вздох, мне потребовалось 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"... но за нами следует плюс!

1 + 2 как регулярное выражение

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

Несколько окончательных мыслей

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

Ответ 3

Вы хотите grepl:

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

Ответ 4

Используйте эту функцию из пакета 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

Ответ 5

На всякий случай вам также хотелось бы проверить, содержит ли строка (или набор строк) несколько подстрок, вы также можете использовать '|' между двумя подстроками.

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

Вы получите

[1]  TRUE FALSE FALSE  TRUE

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

Ответ 6

Вы можете использовать grep

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

Ответ 7

Используйте grep или grepl , но помните, хотите ли вы использовать регулярные выражения.

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

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

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

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

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

Ответ 8

Также можно сделать с помощью библиотеки 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