Fer*_*ndo 3 regex r pattern-matching
我需要根据字符向量模式验证字符串。我当前的代码是:
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)
}
Run Code Online (Sandbox Code Playgroud)
例子:
w.valid = 'special!'
w.invalid = 'test-me'
check.pattern(w.valid) #TRUE
check.pattern(w.invalid) #FALSE
Run Code Online (Sandbox Code Playgroud)
我想这非常慢......有没有更快的方法来做到这一点?也许是正则表达式?谢谢!
PS:感谢大家的精彩回答。我的目标是构建一个 29 x 29 矩阵,其中行名称和列名称是允许的字符。然后我迭代一个巨大文本文件的每个单词并构建一个“字母优先级”矩阵。例如,考虑单词“special”,从第一个字符开始:
row s, col p -> increment 1
row p, col e -> increment 1
row e, col c -> increment 1
... and so on.
Run Code Online (Sandbox Code Playgroud)
我的代码的瓶颈是向量分配,我是“追加”而不是预先分配最终向量,因此代码执行需要 30 分钟,而不是 20 秒!
有一些内置函数可以清理您的代码。我认为您没有充分利用正则表达式的全部功能。
这里最突出的问题是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
Run Code Online (Sandbox Code Playgroud)
接下来,使用花括号表示重复次数和一些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
Run Code Online (Sandbox Code Playgroud)
最后,您可以将正则表达式内部化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
Run Code Online (Sandbox Code Playgroud)