Извлечение элемента из строки - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь извлечь элемент между двумя тегами HTML без каких-либо пакетов.

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

string <- c("<tb example", "<TEXT>", "some text", "<TEXT>", "<TEXT> some more text <TEXT>")

Я хочу извлечь элемент (некоторый текст), которыймежду первыми двумя элементами TEXT.

Я пытался использовать grelp и gregexpr, но не могу заставить это работать.

string[grepl("<TEXT>(.*?)<TEXT>", string, ignore.case = F)]
regmatches(string,gregexpr("<TEXT>", string, ignore.case = F))

Спасибо

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

Сначала объедините ваш вектор строк в одну строку, затем используйте пакет stringr для регулярного выражения

library(stringr)

string <- c("<tb example", "<TEXT>", "some text", "<TEXT>", "<TEXT> some more text <TEXT>")
string_c <- paste(string, collapse = " ")

# Find the first occurrence
res <- str_match(string_c, "<TEXT> (.*?) <TEXT>")

res[2]
#[1] "some text"
0 голосов
/ 28 сентября 2018

За исключением 3a, они предполагают, что вы ищете первую последовательность 3 длины string вида <TEXT> что-то <TEXT>;однако, если между последовательными <TEXT> компонентами разрешено любое число векторных компонентов string, используйте 3a или 4a.

1) Если string содержит хотя бы 3 элемента,создайте матрицу с движущимся окном из трех столбцов m и вычислите логический вектор ok, который равен TRUE для строк, столбцы 1 и 3 которых равны <TEXT>.Возьмем первый элемент второго столбца m, в котором есть строка, для которой ok TRUE.

Если совпадений нет, этот код возвращает символьный вектор нулевой длины.Пакеты не используются.

m <- embed(string, 3)
ok <- !rowSums(m[, -2, drop = FALSE] != "<TEXT>")
head(m[ok, 2], 1)
## [1] "some text"

2) Вариантом выше для каждой строки e является возврат среднего элемента, если первый и последний элементы <TEXT> и нет.Затем удалите NA и возьмите первый элемент из того, что осталось.

e <- embed(string, 3)
Select <- function(x) ifelse(all(x[-2] == "<TEXT>"), x[2], NA)
head(na.omit(apply(e, 1, Select)), 1)
## [1] "some text"

3) Другой базовый подход заключается в создании вектора группировки g той же длины, что и * 1031.* который увеличивается на 1 каждый раз, когда встречается <TEXT>.Затем используйте tapply, чтобы извлечь второй элемент каждой группы, имеющий длину 2 или NA, если другая длина.Удалите элементы NA и возьмите первое из того, что осталось.Он возвращает символьный вектор нулевой длины, если нет соответствующих подпоследовательностей.

g <- cumsum(string == "<TEXT>")
Select2 <- function(x) if (length(x) == 2) x[2] else NA
ta <- tapply(string[g > 0], g[g > 0], Select2)
as.character(head(na.omit(c(ta)), 1))
## [1] "some text"

3a) Если между <TEXT> компонентами допустимо более одного компонента string, измените этоследующие.Возвращает NULL, если нет соответствующих подпоследовательностей.

g <- cumsum(string == "<TEXT>")
ta <- tapply(string[g > 0], g[g > 0], function(x) x[-1], simplify = FALSE)
unname(unlist((head(ta, 1))))
## [1] "some text"

4) Находит элемент после каждого <TEXT> элементов и выбирает первый из них.Если есть только один <TEXT>, он возвращает элемент после него и возвращает символьный вектор 0 длины, если вообще нет элементов <TEXT> или если единственный элемент <TEXT> появляется в конце входного вектора.

head(string[c(FALSE, head(string, -1) == "<TEXT>")], 1)
## [1] "some text"

4a) Если между элементами <TEXT> может находиться более одного элемента, используйте это вместо этого.Обратите внимание, что это возвращает NULL, если существует менее двух <TEXT> элементов.Добавьте else ногу к if, если вы хотите вернуть что-то еще в этом случае.

ix <- head(which(string == "<TEXT>"), 2)
if (length(ix) == 2) string[seq(ix[1] + 1, ix[2] - 1)]
## [1] "some text"
0 голосов
/ 28 сентября 2018

Концепция регулярных выражений здесь не сработает, потому что у вас есть вектор, а не строка.Идея сделать это для вектора может состоять в том, чтобы идентифицировать первые два <TEXT>, использовать seq для завершения последовательности, а затем setdiff, чтобы выделить желаемое значение, то есть

v1 <- which(string == '<TEXT>')[1]
v2 <- which(string == '<TEXT>')[2]

string[setdiff(seq(v1, v2), c(v1, v2))]
#[1] "some text"
...