Как Grep может учитывать несколько вхождений подряд?

#r

#r

Вопрос:

скажем, у меня есть:

 test <- c("you", "he", "I", "you are", "you you")

grep("you", test, value = FALSE)
  

это дает мне [1] 1 4 5

что я могу сделать, чтобы учесть двойное вхождение ‘you’ в 5, возможно, получить результат: [1] 1 4 5 5 вместо этого?

Комментарии:

1. разве вектор, подобный 1 0 0 1 2 более полезному? rep(seq_along(test), stringr::str_count(test, 'you'))

2. @rawr это было просто предложение, просто 4 было бы наиболее полезным результатом в моем случае, я думаю, но я пока не совсем уверен. на самом деле точный формат вывода не имеет значения.

Ответ №1:

За исключением (3), все это только две строки кода, и, за исключением (1), все используют только базовую R. Все принимают общие регулярные выражения, за исключением (2) и (5), которые предполагают более строгое предположение о фиксированных строках — в примере вопроса используется фиксированная строка.

(1) кажется самым простым при поддержке регулярных выражений, но (4) лишь немного сложнее, хотя все еще поддерживает регулярные выражения и использует только базовый R.

1) strapplyc strapplyc извлекает список всех you вхождений, по одному вектору на компонент test , а затем lengths выдает длину каждого из этих векторов freq . Наконец, используйте rep , чтобы преобразовать это в желаемую форму. Это решение или (4) кажется самым простым из тех, которые мы представляем.

 library(gsubfn)

freq <- lengths(strapplyc(test, "you"))  # 1 0 0 1 2
rep(seq_along(freq), freq)
[1] 1 4 5 5
  

2) gregexpr 1 Это похоже на последнее, за исключением того, что оно использует gregexpr вместо strapplyc . Проблема gregexpr заключается в его нерегулярном выводе, когда он сообщает об отсутствии вхождений как -1, поэтому мы добавляем «you» к каждому элементу ввода, а затем берем длины минус 1, чтобы не считать добавленные you . Этот вариант лишь немного сложнее с дополнительным учетом того, что нечетный способ gregexpr указывает на отсутствие совпадений; однако у него есть то преимущество, что он использует только базовое R, но для этого требуется, чтобы поисковый запрос был фиксированным, а не регулярным выражением.

 freq <- lengths(gregexpr("you", paste(test, "you"))) - 1
rep(seq_along(freq), freq)
  

3) gregexpr 2 Это также использует gregexpr , но использует другой подход к преобразованию его в желаемую форму. Преобразуйте g выходные gregexpr данные в data.frame с помощью stack . stack требуется, чтобы список ввода был назван, и мы также должны удалить вхождения -1, g чтобы получить правильный ответ.. Результатом, сформированным с помощью stack , является фрейм данных с двумя столбцами, в котором столбец factor ind содержит решение. Наконец, преобразуйте ind в целое число.

 g <- gregexpr("you", test)
names(g) <- seq_along(g)
as.integer(as.character(stack(lapply(g, setdiff, -1L))$ind))

## [1] 1 4 5 5
  

4) gregexpr 3 Удаляет значения -1 в gregexpr выходных данных, чтобы lengths их можно было использовать. Он использует только базовый R, а также работает с регулярными выражениями.

 g <- gregexpr("you", test)
rep(seq_along(g), lengths(lapply(g, setdiff, -1L)))
## [1] 1 4 5 5
  

5) подсчет.поля Другим базовым решением R является использование count.fields , которое будет подсчитывать поля между вхождениями you , поэтому мы вычитаем единицу, чтобы получить вхождения you самого себя. Это может обрабатывать только фиксированные строки, тогда как другие решения могут обрабатывать регулярные выражения.

 freq <- count.fields(textConnection(test), sep = "you") - 1
rep(seq_along(freq), freq)
## [1] 1 4 5 5
  

Комментарии:

1. круто, спасибо, это помогло бы, однако я бы не хотел просто копировать это, поскольку это определенно не в моей лиге. если я просто выполняю gregexpr («вы», тест), я получаю результат, с которым я не могу справиться, почему это? или вы можете кратко объяснить свой код?

2. большое вам спасибо! можно ли мне просто использовать подход gregexpr 2 для университетского задания? я упомяну, что у меня есть это из Интернета, хотя это действительно очень очевидно.

3. Я не против, если ваш инструктор согласится.

4. Добавили 4) gregexpr 3