2

文字ベクトル パターンに対して文字列を検証する必要があります。私の現在のコードは次のとおりです。

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 マトリックスを作成することでした。次に、巨大なテキスト ファイルの各単語を繰り返し処理し、「文字の優先順位」マトリックスを構築します。たとえば、最初の文字から始まる「special」という単語を考えてみましょう。

row s, col p -> increment 1
row p, col e -> increment 1
row e, col c -> increment 1
... and so on.

私のコードのボトルネックはベクトルの割り当てでした。最終的なベクトルを事前に割り当てるのではなく「追加」していたため、コードの実行に 20 秒ではなく 30 分かかっていました。

4

2 に答える 2

5

コードをクリーンアップできる組み込み関数がいくつかあります。そして、あなたは正規表現の力をフルに活用していないと思います。

ここでの大きな問題はstrsplit. 正規表現を使用している場合、文字ごとに等しいかどうかを比較するのは非効率的です。ここでのパターンでは、角かっこ表記を使用して、必要な文字をフィルター処理しています。*は任意の回数 (0 を含む) 繰り返しますが、^$記号は行の最初と最後を表すため、他に何もありません。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
于 2013-01-31T19:11:40.423 に答える
1

希望するパターンを正しく理解している場合は、次のような形式の正規表現が必要になります。

^\\s*[a-z!\\.\\?]{MIN,MAX}\\s*$

ここで、MINはストリングの最小長に置き換えられ、MAXはストリングの最大長に置き換えられます。最大長がない場合は、MAXとコンマを省略できます。同様に、中括弧自体を含む{}内のすべてが最大値でも最小値でもない場合は、前の項目が0回以上一致することを意味する*に置き換えることができます。これは{0}と同等です。

これにより、正規表現は、先頭と末尾の空白の後のすべての文字が*小文字*バング(感嘆符)*疑問符のセットからのものである文字列にのみ一致するようになります。

これは私がよく知っているPerlスタイルの正規表現で書かれていることに注意してください。私の研究のほとんどは、Rテキスト処理のためのこのwikiにありました。

関数が遅くなる理由は、文字列をいくつかの小さな文字列に分割するという余分なオーバーヘッドです。これは、正規表現と比較して多くのオーバーヘッドがあります(または、文字列を手動で反復して、最後に到達するか無効な文字が見つかるまで各文字を比較します)。また、このアルゴリズムでは、分割によってn個の文字列が生成されるため、O(n)のパフォーマンスレートが保証されることを忘れないでください。これは、失敗した文字列でさえ、文字列を拒否するために少なくともn個のアクションを実行する必要があることを意味します。

うまくいけば、これにより、パフォーマンスの問題が発生した理由が明らかになります。

于 2013-01-31T19:45:44.123 に答える