我正在尝试检查包含许多元素的向量与包含字符串的数据框列之间的匹配。
vec <- c("KIND", "Quest")
string <- ("lieberkind", "kind", "KIND", "Quest Nutrition", "Quest")
x <- sapply(vec, function (x) grepl(x, string, ignore.case = TRUE))
结果如下:
> x
KIND Quest
[1,] TRUE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
问题在于“KIND”的第一个结果,它最终为'lieberkind'生成一个TRUE值。
通常情况下,我会添加一个令牌来指定字边界,如:
grepl("\\bKIND\\b", string, ignore.case = TRUE)
[1] FALSE TRUE TRUE FALSE FALSE
但是当我使用sapply
将向量的每个元素与字符串的每个元素进行比较时,我不知道如何做到这一点。
我显然不能这样做:
x <- sapply(vec, function (x) grepl(\\bx\\b, string, ignore.case = TRUE))
我该如何解决这个问题?
答案 0 :(得分:2)
有多种方法可以检查字边界,它们取决于您的数据。如果您需要使用单词边界,请使用
x <- sapply(vec, function (x) grepl(paste0("\\b",x,"\\b"), string, ignore.case = TRUE))
或Jota's recommended equivalent:
x <- sapply(vec, function (x) grepl(sprintf("\\b%s\\b", x), string, ignore.case = TRUE))
但是,如果您的vec
包含内部带有特殊字符的条目(注意:不在开头或结尾),那么您需要使用
x <- sapply(vec, function (x) grepl(paste0("\\b",gsub("([][/\\\\^$*+?.()|{}-])", "\\\\\\1", x),"\\b"), string, ignore.case = TRUE))
最后,如果你将单词边界定义为空白字符串或字符串的开头/结尾,我宁愿推荐一个像
这样的PCRE正则表达式x <- sapply(vec, function (x) grepl(paste0("(?<!\\S)",gsub("([][/\\\\^$*+?.()|{}-])", "\\\\\\1", x),"(?!\\S)"), string, ignore.case = TRUE, perl=TRUE))
测试数据的所有3个案例的结果如下:
KIND Quest
[1,] FALSE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
P.S。无论您使用paste0
还是sprintf
,都会得到相同的结果。