如何防止regmatches下降不匹配?

col*_*ang 15 regex r

我想捕获第一场比赛,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"
Run Code Online (Sandbox Code Playgroud)

所以我期待"a",NA,"a","aa"

the*_*ail 17

坚持regexpr:

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


Ric*_*rta 10

使用regexec替代,因为它返回一个列表,让您赶上character(0)之前的unlist荷兰国际集团

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

 # [1] "a"  NA   "a"  "aa"
Run Code Online (Sandbox Code Playgroud)

  • 自从在最近的 R 版本中引入了“lengths()”以来,“unlist({R[lengths(R)==0] &lt;- NA; R})”现在也可以工作了。 (2认同)

lmo*_*lmo 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" ""
Run Code Online (Sandbox Code Playgroud)

所以要提取你想要的东西(用""代替NA),你可以使用sapply如下:

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

此时,如果你真的想要NA而不是"",你可以使用

is.na(myVec) <- nchar(myVec) == 0L
myVec
[1] "a"  NA   "a"  "aa"
Run Code Online (Sandbox Code Playgroud)

一些修订:
请注意,您可以将最后两行折叠为一行:

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

默认数据类型NA是逻辑的,因此使用它将导致额外的数据转换.使用角色版本NA_character_,避免这种情况.

最后一行的更加平滑的提取方法是使用[:

sapply(myMatch, `[`, 2)
[1] "a"  NA   "a"  "aa"
Run Code Online (Sandbox Code Playgroud)

所以你可以在一个相当可读的单行中完成整个事情:

sapply(regmatches(x, m, invert=NA), `[`, 2)
Run Code Online (Sandbox Code Playgroud)