343

文字列が別の文字列のサブセットであるかどうかを判断しようとしています。例えば:

chars <- "test"
value <- "es"

「value」が文字列「chars」の一部として表示される場合は、TRUEを返したいです。次のシナリオでは、falseを返したいと思います。

chars <- "test"
value <- "et"
4

9 に答える 9

479

grepl関数を使用する

grepl( needle, haystack, fixed = TRUE)

そのようです:

grepl(value, chars, fixed = TRUE)
# TRUE

詳細を確認するために使用?greplします。

于 2012-04-12T17:28:43.197 に答える
201

答え

ため息をつく、この簡単な質問の答えを見つけるのに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

解釈

grepLinux実行可能ファイルにちなんで名付けられました。これは、それ自体が「G lobal R egular E xpression P rint」の頭字語であり、入力行を読み取り、指定した引数と一致する場合はそれらを出力します。「グローバル」とは、入力行のどこでも一致が発生する可能性があることを意味します。以下で「正規表現」について説明しますが、文字列(Rはこれを「文字」と呼びますclass("abc"))と「印刷」を一致させるためのよりスマートな方法です。 "これはコマンドラインプログラムであるため、出力を出力するということは、出力文字列に出力することを意味します。

現在、grepプログラムは基本的に、入力行から出力行までのフィルターです。また、Rのgrep関数も同様に入力の配列を受け取るようです。私にはまったく知られていない理由で(私は約1時間前にRで遊び始めただけです)、一致のリストではなく、一致するインデックスのベクトルを返します。

しかし、元の質問に戻ると、私たちが本当に望んでいるのは、干し草の山で針が真/偽の値であるかどうかを知ることです。彼らは明らかに、この関数greplに「grep」のよう名前を付けることを決定しましたが、「論理」の戻り値を使用します(たとえば、真と偽の論理値を呼び出しますclass(TRUE))。

これで、名前の由来とその意味がわかりました。正規表現に戻りましょう。引数は文字列ですが、正規表現(以降:regex)を作成するために使用されます。正規表現は文字列を照合する方法です(この定義がイライラする場合は、手放してください)。たとえば、正規表現aは文字と一致し"a"、正規表現a*は文字と"a"0回以上一致し、正規表現a+は文字と"a"1回以上一致します。したがって、上記の例では、正規表現として扱われる場合、検索している針は1+2「1つ以上の1の後に2が続く」ことを意味します...しかし、私たちの針の後にはプラスが続きます!

正規表現としての1+2

したがって、grepl設定せずに使用した場合fixed、針が誤って干し草の山になり、それが誤って頻繁に機能する可能性があります。これは、OPの例でも機能することがわかります。しかし、それは潜在的なバグです!入力が正規表現ではなく文字列であることを伝える必要があります。これは明らかにfixed目的です。なぜ修正されたのですか?手がかりはありません。この回答をブックマークしてください。おそらく、覚える前にさらに5回調べる必要があります。

いくつかの最終的な考え

コードが優れているほど、コードを理解するために知っておく必要のある履歴は少なくなります。すべての引数は少なくとも2つの興味深い値を持つことができます(そうでなければ引数である必要はありません)。ドキュメントにはここに9つの引数がリストされています。つまり、少なくとも2 ^ 9 = 512の方法で呼び出すことができます。これは、多くの作業が必要です。書き込み、テスト、および記憶...そのような関数を分離します(それらを分割し、相互の依存関係を削除し、文字列のものは正規表現のものとは異なり、ベクトルのものとは異なります)。一部のオプションも相互に排他的であり、ユーザーにコードの誤った使用方法を提供しないでください。つまり、問題のある呼び出しは、論理的に無意味ではなく(存在しないオプションを渡すなど)、構造的に無意味である必要があります(必要な場合)それを説明するために警告を発します)。比喩的に言えば:10階横の玄関ドアを壁に替えるのは、使用を警告する看板を掛けるよりはましですが、どちらもどちらよりもいいです。インターフェイスでは、関数は呼び出し元ではなく、引数がどのように見えるかを定義します(呼び出し元は関数に依存しているため、誰もが呼び出したいと思う可能性のあるすべてのものを推測すると、関数も呼び出し元に依存します。このタイプ周期的な依存関係があると、システムがすぐに詰まり、期待するメリットが得られなくなります)。タイプを曖昧にすることに非常に注意してください、それは次のようなものの設計上の欠陥です 誰もがそれを呼び出したいと思うかもしれないすべてを推測すると、関数は呼び出し元にも依存します。このタイプの周期的な依存関係は、システムをすぐに詰まらせ、期待する利点を提供しません)。タイプを曖昧にすることに非常に注意してください、それは次のようなものの設計上の欠陥です 誰もがそれを呼び出したいと思うかもしれないすべてを推測すると、関数は呼び出し元にも依存します。このタイプの周期的な依存関係は、システムをすぐに詰まらせ、期待する利点を提供しません)。タイプを曖昧にすることに非常に注意してください、それは次のようなものの設計上の欠陥ですTRUEおよび0"abc"はすべてベクトルです。

于 2016-10-15T17:48:53.673 に答える
39

あなたが欲しいgrepl

> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE
于 2012-04-12T17:28:40.123 に答える
32

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
于 2014-03-14T09:46:12.033 に答える
32

また、 「stringr」ライブラリを使用して実行できます。

> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE

### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1]  TRUE FALSE  TRUE FALSE  TRUE
于 2017-06-14T02:38:39.913 に答える
23

文字列(または文字列のセット)に複数のサブ文字列が含まれているかどうかも確認したい場合は、「|」を使用することもできます。2つの部分文字列の間。

>substring="as|at"
>string_vector=c("ass","ear","eye","heat") 
>grepl(substring,string_vector)

あなたは得るでしょう

[1]  TRUE FALSE FALSE  TRUE

最初の単語には「as」という部分文字列があり、最後の単語には「at」という部分文字列が含まれているためです。

于 2015-01-25T09:04:18.830 に答える
10

grepまたはを使用grepl しますが、正規表現を使用するかどうかに注意してください。

デフォルトでは、grepおよびrelatedは、リテラルの部分文字列ではなく、一致する正規表現を取ります。それを予期しておらず、無効な正規表現で一致させようとすると、機能しません。

> grep("[", "abc[")
Error in grep("[", "abc[") : 
  invalid regular expression '[', reason 'Missing ']''

真の部分文字列テストを実行するには、を使用しますfixed = TRUE

> grep("[", "abc[", fixed = TRUE)
[1] 1

正規表現が必要な場合は素晴らしいですが、それはOPが求めているようには見えません。

于 2016-04-13T21:59:25.867 に答える
7

使用できますgrep

grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)
于 2012-04-12T17:29:03.240 に答える
1

ここでの同様の問題:文字列とキーワードのリストが与えられた場合、文字列に含まれているキーワードがある場合はそれを検出します。

stringrこのスレッドからの推奨事項は、とを提案しstr_detectますgreplmicrobenchmarkパッケージのベンチマークは次のとおりです。

使用する

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

ご覧のとおり、実用的な文字列とキーワードのベクトルを使用str_detectしたキーワード検索の5,000回以上の反復は、よりもかなり優れたパフォーマンスを発揮します。greplgreplstr_detect

r結果は、文字列に含まれているキーワードがある場合はそれを識別するブールベクトルです。

したがって、を使用greplして、文字列にキーワードが含まれているかどうかを判断することをお勧めします。

于 2020-06-07T16:34:43.677 に答える