使用以下代码从字符串列表中仅选择字母数字字符串:
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"
?
答案 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"