Как предотвратить повторные совпадения регматиков?

Я хотел бы зафиксировать первое совпадение и вернуть NA, если совпадения нет.

regexpr("a+", c("abc", "def", "cba a", "aa"), perl=TRUE)
# [1]  1 -1  3  1
# attr(,"match.length")
# [1]  1 -1  1  2

x <- c("abc", "def", "cba a", "aa")
m <- regexpr("a+", x, perl=TRUE)
regmatches(x, m)
# [1]  "a"  "a"  "aa"

Поэтому я ожидал "a", NA, "a", "aa"

Ответ 1

Пребывание с regexpr:

r <- regexpr("a+", x)
out <- rep(NA,length(x))
out[r!=-1] <- regmatches(x, r)
out
#[1] "a"  NA   "a"  "aa"

Ответ 2

используйте regexec вместо этого, поскольку он возвращает список, который позволит вам поймать character(0) до unlist ing

 R <- regmatches(x, regexec("a+", x))
 unlist({R[sapply(R, length)==0] <- NA; R})

 # [1] "a"  NA   "a"  "aa"

Ответ 3

В R 3.3.0 можно извлечь как совпадения, так и несоответствующие результаты, используя аргумент invert = NA. Из справочного файла написано

если инвертирование равно NA, regmatches извлекает как несоответствующие, так и совпадающие подстроки, всегда начинающиеся и заканчивающиеся несоответствием (пусто, если совпадение произошло в начале или в конце соответственно).

Вывод представляет собой список, как правило, в большинстве случаев представляющий интерес (соответствующий одному шаблону), regmatches с этим аргументом возвращают список с элементами длиной 3 или 1. 1 - случай, когда совпадений не найдено, и 3 это случай со спичкой.

myMatch <- regmatches(x, m, invert=NA)
myMatch
[[1]]
[1] ""   "a"  "bc"

[[2]]
[1] "def"

[[3]]
[1] "cb" "a"  " a"

[[4]]
[1] ""   "aa" ""

Таким образом, чтобы извлечь то, что вы хотите (с "" вместо NA), вы можете использовать sapply следующим образом:

myVec <- sapply(myMatch, function(x) {if(length(x) == 1) "" else x[2]})
myVec
[1] "a"  ""   "a"  "aa"

На этом этапе, если вы действительно хотите NA вместо "", вы можете использовать

is.na(myVec) <- nchar(myVec) == 0L
myVec
[1] "a"  NA   "a"  "aa"

Некоторые изменения:
Обратите внимание, что вы можете свернуть последние две строки в одну строку:

myVec <- sapply(myMatch, function(x) {if(length(x) == 1) NA_character_ else x[2]})

Тип данных по умолчанию NA является логическим, поэтому его использование приведет к дополнительным преобразованиям данных. Использование версии NA_character_ позволяет избежать этого.

Еще один способ извлечения для последней строки - использовать [:

sapply(myMatch, '[', 2)
[1] "a"  NA   "a"  "aa"

Таким образом, вы можете сделать все это в одной удобочитаемой строке:

sapply(regmatches(x, m, invert=NA), '[', 2)

Ответ 4

Используя более или менее ту же конструкцию, что и ваша -

chars <- c("abc", "def", "cba a", "aa")    

chars[
   regexpr("a+", chars, perl=TRUE) > 0
][1] #abc

chars[
   regexpr("q", chars, perl=TRUE) > 0
][1]  #NA

#vector[
#    find all indices where regexpr returned positive value i.e., match was found
#][return the first element of the above subset]

Изменить - Кажется, я неправильно понял вопрос. Но так как два человека нашли это полезным, я оставлю его.