我需要根据字符向量模式验证字符串。我目前的代码是:
trim <- function (x) gsub("^\\s+|\\s+$", "", x)
# valid pattern is lowercase alphabet, '.', '!', and '?' AND
# the string length should be >= than 2
my.pattern = c(letters, '!', '.', '?')
check.pattern = function(word, min.size = 2)
{
word = trim(word)
chars = strsplit(word, NULL)[[1]]
all(chars %in% my.pattern) && (length(chars) >= min.size)
}
示例:
w.valid = 'special!'
w.invalid = 'test-me'
check.pattern(w.valid) #TRUE
check.pattern(w.invalid) #FALSE
这是非常慢的我猜...有更快的方法吗?正则表达式可能吗? 谢谢!
PS:非常感谢大家的回答。我的目标是构建一个29 x 29矩阵, 行名和列名是允许的字符。然后我迭代一个巨大的文本文件的每个单词,并建立一个'字母优先'矩阵。例如,从第一个char开始考虑单词'special':row s, col p -> increment 1
row p, col e -> increment 1
row e, col c -> increment 1
... and so on.
我的代码的瓶颈是向量分配,我正在'追加'而不是预先分配最终的向量,因此代码需要30分钟才能执行,而不是20秒! / p>
答案 0 :(得分:4)
有一些内置函数可以清理代码。而且我认为你没有充分利用正则表达式的全部功能。
这里的明显问题是strsplit
。当你有正则表达式时,逐个字符地比较事物的相等性是低效的。此处的模式使用方括号表示法来过滤所需的字符。 *
适用于任意数量的重复(包括零),而^
和$
符号代表行的开头和结尾,因此没有其他内容。 nchar(word)
与length(chars)
相同。将&&
更改为&
会使函数矢量化,因此您可以输入字符串向量并获取逻辑向量作为输出。
check.pattern.2 = function(word, min.size = 2)
{
word = trim(word)
grepl(paste0("^[a-z!.?]*$"),word) & nchar(word) >= min.size
}
check.pattern.2(c(" d ","!hello ","nA!"," asdf.!"," d d "))
#[1] FALSE TRUE FALSE TRUE FALSE
接下来,使用花括号表示重复次数和一些paste0
,模式可以使用你的min.size:
check.pattern.3 = function(word, min.size = 2)
{
word = trim(word)
grepl(paste0("^[a-z!.?]{",min.size,",}$"),word)
}
check.pattern.3(c(" d ","!hello ","nA!"," asdf.!"," d d "))
#[1] FALSE TRUE FALSE TRUE FALSE
最后,您可以从trim
:
check.pattern.4 = function(word, min.size = 2)
{
grepl(paste0("^\\s*[a-z!.?]{",min.size,",}\\s*$"),word)
}
check.pattern.4(c(" d ","!hello ","nA!"," asdf.!"," d d "))
#[1] FALSE TRUE FALSE TRUE FALSE
答案 1 :(得分:1)
如果我理解你正确需要的模式,你会想要一个类似格式的正则表达式:
^\\s*[a-z!\\.\\?]{MIN,MAX}\\s*$
其中MIN被替换为字符串的最小长度,MAX被替换为字符串的最大长度。如果没有最大长度,则可以省略MAX和逗号。同样地,如果既没有最大值也没有最小值{}内的所有内容,包括括号本身都可以用*代替,这表示前一项将匹配零次或多次;这相当于{0}。
这确保正则表达式只匹配字符串,其中任何前导和尾随空格之后的每个字符都来自 *小写字母 *一声巨响(感叹号) *一个问号
请注意,这是用Perl风格的正则表达式编写的,因为它是我更熟悉的;我的大部分研究都在this wiki for R text processing。
函数缓慢的原因是将字符串拆分为多个较小字符串的额外开销。与正则表达式相比,这是一个很大的开销(甚至是对字符串的手动迭代,比较每个字符,直到到达结尾或找到无效字符)。还要记住,此算法确保了O(n)性能速率,因为拆分会导致生成n个字符串。这意味着即使是FAILING字符串也必须至少执行n次操作才能拒绝该字符串。
希望这可以澄清您遇到性能问题的原因。