15

我想捕获第一个匹配项,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”

4

4 回答 4

18

住在一起regexpr

r <- regexpr("a+", x)
out <- rep(NA,length(x))
out[r!=-1] <- regmatches(x, r)
out
#[1] "a"  NA   "a"  "aa"
于 2013-10-04T02:11:43.833 回答
12

改为使用regexec,因为它返回一个列表,允许您在ingcharacter(0)之前捕获 'sunlist

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

 # [1] "a"  NA   "a"  "aa"
于 2013-10-04T01:43:20.383 回答
7

在 R 3.3.0 中,可以使用 invert=NA 参数同时提取匹配和不匹配的结果。从帮助文件中,它说

如果 invert 为 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)
于 2016-06-15T22:41:54.033 回答
1

使用或多或少与您相同的结构-

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]

编辑 - 好像我误解了这个问题。但既然有两个人发现这很有用,我就让它留下来。

于 2013-10-04T02:00:32.670 回答