文字列が別の文字列のサブセットであるかどうかを確認しようとしています。例えば:
chars <- "test"
value <- "es"
「値」が文字列「chars」の一部として表示される場合は、TRUEを返します。次のシナリオでは、falseを返します。
chars <- "test"
value <- "et"
fixed=TRUE
か、静かにそして微妙にデータを破壊するバグが発生します。
文字列が別の文字列のサブセットであるかどうかを確認しようとしています。例えば:
chars <- "test"
value <- "es"
「値」が文字列「chars」の一部として表示される場合は、TRUEを返します。次のシナリオでは、falseを返します。
chars <- "test"
value <- "et"
fixed=TRUE
か、静かにそして微妙にデータを破壊するバグが発生します。
回答:
grepl
関数を使用する
grepl(value, chars, fixed = TRUE)
# TRUE
?grepl
詳細を調べるために使用します。
vec <- replicate(100000, paste( sample(letters, 10, replace=TRUE), collapse='') )
。短い文字列の束で1つの一致を見つけてみてください。
system.time(a <- grepl("abc", vec))
とsystem.time(a <- grepl("abc", vec, fixed=TRUE))
し、fixed=TRUE
どちらかといえばやや遅く、まだです。これらの短い文字列では違いはあまりわかりfixed=TRUE
ませんが、それでも高速であるようには見えません。ただし、fixed=TRUE
実際にヒットするのは長い文字列にあることを指摘してくれてありがとう。
ため息、この簡単な質問の答えを見つけるのに45分かかりました。答えは:grepl(needle, haystack, fixed=TRUE)
# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE
# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE
grep
それ自体が「G lobal R egular E xpression P rint 」の頭字語であるlinux実行可能ファイルにちなんで名付けられ、入力行を読み取って、指定した引数と一致する場合はそれらを出力します。「グローバル」は、一致が入力行のどこでも発生する可能性があることを意味しました。以下の「正規表現」について説明しますが、アイデアは、文字列を一致させるためのよりスマートな方法です(Rはこの「文字」を呼び出します。class("abc")
)と「印刷」 "これはコマンドラインプログラムであるため、出力を発行すると、出力文字列に出力されます。
現在、grep
プログラムは基本的に、入力行から出力行までのフィルターです。そして、Rのgrep
関数も同様に入力の配列を取るようです。私にはまったくわからない理由のため(私は約1時間前にRで遊んだばかりです)、一致のリストではなく、一致するインデックスのベクトルを返します。
しかし、元の質問に戻って、私たちが本当に欲しいのは、干し草の山に針が見つかったかどうか、真/偽の値を知ることです。彼らは明らかに、この関数に名前を付けることにしましたgrepl
「はgrep」のとしてではなく「と、L(彼らは例えば、真と偽の論理値を呼び出し、戻り値ogical」class(TRUE)
)。
これで、名前がどこから来たのか、何をするのかがわかりました。正規表現に戻りましょう。引数は文字列ですが、正規表現(以降、regex)を構築するために使用されます。正規表現は、文字列を照合する方法です(この定義でイライラした場合は、そのままにします)。たとえば、正規表現a
は文字"a"
に一致し、正規表現a*
は文字に"a"
0回以上一致し、正規表現a+
は文字に"a"
1回以上一致します。したがって、上記の例では、検索している針は1+2
、正規表現として扱われる場合、「1つ以上の1の後に2が続く」ことを意味します...しかし、私たちの針の後にはプラスが続きます!
したがって、を使用せgrepl
ずにを使用した場合fixed
、針が誤って干し草の山になり、偶然かなり頻繁に機能するようになるため、OPの例でも機能することがわかります。しかし、それは潜在的なバグです!入力が正規表現ではなく文字列であることを伝える必要がありますfixed
。これは明らかに目的です。なぜ修正されたのですか?手がかりがありません。この回答をブックマークしてください。覚える前に、さらに5回調べる必要があります。
コードが優れているほど、それを理解するために知る必要がある履歴が少なくなります。すべての引数は、少なくとも2つの興味深い値を持つことができます(そうでない場合、引数である必要はありません)。ドキュメントには、ここに9つの引数がリストされています。つまり、少なくとも2 ^ 9 = 512の方法で呼び出すことができます。書き、テストし、覚えておいてください...そのような関数を分離します(それらを分割し、相互の依存関係を削除します。文字列は正規表現とは異なり、ベクトルとは異なります)。一部のオプションは相互に排他的でもあります。つまり、ユーザーにコードの誤った使用方法を与えないでください。つまり、問題のある呼び出しは、論理的に無意味ではない(存在するオプションを渡すなど)構造的に無意味である必要があります。それを説明する警告を発します)。比喩的に言えば:10階の側面にある正面玄関を壁に置き換えることは、その使用を警告する標識をぶら下げるよりも優れていますが、どちらもどちらも優れていません。インターフェースでは、関数は呼び出し元ではなく引数の外観を定義します(呼び出し元は関数に依存しているため、誰もがそれを呼び出す可能性のあるすべてのものを推測すると、関数も呼び出し元に依存するため、この型周期的な依存関係があると、システムがすぐに詰まり、期待するメリットが得られません)。型の等価性に非常に注意してください。これは、設計上の欠陥であり、誰もが呼び出す可能性のあるすべてのものを推測すると、関数も呼び出し元に依存するようになり、このタイプの循環依存関係はシステムをすぐに詰まらせ、期待する利点を提供しません)。型の等価性に非常に注意してください。これは、設計上の欠陥であり、誰もがそれを呼び出したいと思うかもしれないすべてを推測すると、関数も呼び出し元に依存するようになり、このタイプの循環依存はシステムをすぐに詰まらせ、期待する利点を提供しません)。型の等価性に非常に注意してください。これは、設計上の欠陥であり、TRUE
そして、0
し、"abc"
すべてのベクトルです。
grep
セルではなく行をフィルタリングする場合と同様に、この場合は一致インデックスのベクトルを返すことが適切と思われます。
この関数をstringi
パッケージから使用します。
> stri_detect_fixed("test",c("et","es"))
[1] FALSE TRUE
いくつかのベンチマーク:
library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)
chars <- "es"
library(microbenchmark)
microbenchmark(
grepl(chars, value),
grepl(chars, value, fixed=TRUE),
grepl(chars, value, perl=TRUE),
stri_detect_fixed(value, chars),
stri_detect_regex(value, chars)
)
## Unit: milliseconds
## expr min lq median uq max neval
## grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530 100
## grepl(chars, value, fixed = TRUE) 5.071617 5.110779 5.281498 5.523421 45.243791 100
## grepl(chars, value, perl = TRUE) 1.835558 1.873280 1.956974 2.259203 3.506741 100
## stri_detect_fixed(value, chars) 1.191403 1.233287 1.309720 1.510677 2.821284 100
## stri_detect_regex(value, chars) 6.043537 6.154198 6.273506 6.447714 7.884380 100
grep
またはgrepl
を使用しますが、正規表現を使用するかどうかに注意してください。
デフォルトではgrep
、関連するものは、リテラル部分文字列ではなく、正規表現を使用して一致します。それを期待しておらず、無効な正規表現で照合しようとすると、機能しません。
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
真の部分文字列テストを行うには、を使用しますfixed = TRUE
。
> grep("[", "abc[", fixed = TRUE)
[1] 1
正規表現が必要な場合は素晴らしいですが、OPが求めているようには見えません。
ここで同様の問題:文字列とキーワードのリストを指定して、もしあれば、どのキーワードが文字列に含まれているかを検出します。
このスレッドからの提言を示唆stringr
さんstr_detect
とgrepl
。microbenchmark
パッケージのベンチマークは次のとおりです。
使用する
map_keywords = c("once", "twice", "few")
t = "yes but only a few times"
mapper1 <- function (x) {
r = str_detect(x, map_keywords)
}
mapper2 <- function (x) {
r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}
その後
microbenchmark(mapper1(t), mapper2(t), times = 5000)
我々は気づく
Unit: microseconds
expr min lq mean median uq max neval
mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476 5000
mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837 5000
あなたは使ってキーワード検索の5,000回の繰り返しの上に、見ることができるようにstr_detect
し、grepl
キーワードの実用的な文字列やベクトル、上grepl
かなり良くより行ないますstr_detect
。
結果は、r
どのキーワードが文字列に含まれるかを特定するブールベクトルです。
したがって、を使用grepl
して、キーワードが文字列に含まれているかどうかを判断することをお勧めします。
fixed=TRUE
ます。追加する必要があります。そうでない場合は、文字列ではなく正規表現として扱います。2016