过滤/ grep函数表现奇怪

时间:2016-08-18 14:00:48

标签: regex r

使用以下代码从字符串列表中仅选择字母数字字符串:

isValid = function(string){
  return(grep("^[A-z0-9]+$", string))
}

strings = c("aaa", "test@test.com", "", "valid")

print(Filter(isValid, strings))

输出为[1] "aaa" "test@test.com"

为什么"valid"没有输出,为什么输出"test@test.com"

2 个答案:

答案 0 :(得分:5)

Filter函数接受逻辑向量,您提供了数字。使用grepl

isValid = function(string){
  return(grepl("^[A-z0-9]+$", string))
}

strings = c("aaa", "test@test.com", "", "valid")

print(Filter(isValid, strings))
[1] "aaa"   "valid"

为什么没有grep工作?这是由于R将数值强制转化为逻辑和Filter的古怪。

发生了什么,grep("^[A-z0-9]+$", string)正确返回1 4。这是第一个和第四个元素的匹配索引。

但这不是Filter的工作方式。它使用as.logical(unlist(lapply(x, f)))在每个元素上运行条件。

所以它运行isValid(strings[1])然后isValid(strings[2]),依此类推。它创造了这个:

[[1]]
[1] 1

[[2]]
integer(0)

[[3]]
integer(0)

[[4]]
[1] 1

然后,它会在该列表中调用unlist以获取1 1并将其转换为逻辑向量TRUE TRUE。所以最后你得到了:

strings[which(c(TRUE, TRUE))]

变成了

strings[c(1,2)]
[1] "aaa"           "test@test.com"

故事的道德,不要使用Filter:)

答案 1 :(得分:2)

你可以采用与此相反的方向,并排除任何带有标点符号的字符串,即

isValid <- function(string){
  v1 <- string[!string %in% grep('[[:punct:]]', string, value = TRUE)] 
  return(v1[v1 != ''])
  }
isValid(strings)
#[1] "aaa"   "valid"
相关问题