JavaScriptで文字列に別の部分文字列が含まれていることを確認する最も速い方法は?


163

JavaScriptのパフォーマンスの問題に取り組んでいます。だから私は尋ねたいだけです:文字列が別の部分文字列を含むかどうかを確認する最も速い方法は何ですか(私はブール値だけが必要ですか?)あなたのアイデアとサンプルスニペットコードを提案していただけませんか?


固定部分文字列について質問していますか、または正規表現が必要regexですか(タグの使用に少し混乱しています)?
Tim Pietzcker


文字列を空白の周りの配列に分割し、配列の交差を行いませんか?stackoverflow.com/questions/1885557/...
giorgio79

回答:


315

次の2つの可能性があります。

  1. 正規表現

    (new RegExp('word')).test(str)
    // or
    /word/.test(str)
  2. indexOf

    str.indexOf('word') !== -1

正規表現の方が速いようです(少なくともChrome 10では)。

パフォーマンステスト-短い干し草
パフォーマンステスト-長い干し草


2011年更新:

どちらの方法が速いかは確実とは言えません。ブラウザ間の違いは非常に大きいです。Chrome 10 indexOfでは高速のようですが、Safari 5ではindexOf他のどの方法よりも明らかに低速です。

自分の目で確かめてみてください。それはあなたのニーズに依存します。たとえば、正規表現を使用すると、大文字と小文字を区別しない検索がはるかに高速になります。


2018年更新:

人々がテストを実行するのを避けるために、最も一般的なブラウザの現在の結果を示します。パーセンテージは、次に速い結果(ブラウザによって異なります)よりもパフォーマンスが向上していることを示しています。

Chrome: indexOf(〜98%高速)<-- wow
Firefox:キャッシュされたRegExp(〜18%高速)
IE11:キャッシュされたRegExp(〜10%高速)
Edge: indexOf(〜18%高速)
Safari:キャッシュされたRegExp(〜0.4%高速)

正規表現をキャッシュしては次のとおりです。var r = new RegExp('simple'); var c = r.test(str);とは反対に:/simple/.test(str)


3
正規表現は解析時にJavaScriptエンジンによって作成されるため、検索するテキストが事前にわかっている(つまり、変数に格納されていない)場合にのみ、これは少し速くなる可能性があります。あなたが別の文字列変数内の変数に含まれる文字列を検索したい場合は、などの特殊文字をエスケープするRegExpオブジェクトを作成し、文字列を処理する必要があると思いますので、のindexOfは最速です
スティーブン・チョン

経験上、最初に検索するものに.toLowerCaseを使用すると、大文字と小文字を区別せずにindexOfを高速化できます
Hayk Saakian 2013年

MicrosoftのOffice JavaScript APIを使用indexOfしてOffice 2013アプリを作成していますが、使用できません。理由はわかりません。ただし、正規表現を使用することはできます。これはエッジケースですが、同じ問題が発生する場合もあります。
Andy Mercer 14

substr()が可能な解決策の1つではない理由は何ですか?多くの状況では、RegExソリューションよりもはるかに高速だと思います。私はそれがのindexOf()と比較する方法を知りませんが(それはいつもの罰金は、多分、その効果にメモを追加することを、その後のindexOf()よりも悪い実行するので、あなたはそれを残しそうならば。)EDITを: このJSperfリンクショーをいくつかの興味深いです結果。短いバージョン:indexOf()はすべてのメソッドの中で最速ですが、これは文字列の長さや繰り返しパターンによって異なる場合があります。
Byson

1
@Bison:どこを見ればよいかがわかっている場合にのみ、substrを使用できます。私は一般的なソリューションにのみ焦点を当てました。
Felix Kling 14

17

これはうまくいきますか?

string1.indexOf(string2) >= 0

編集:string2に繰り返しパターンが含まれている場合、これはRegExpよりも速くない可能性があります。一部のブラウザでは、indexOfがRegExpよりもはるかに遅い場合があります。コメントを参照してください。

編集2:文字列が非常に長い、または繰り返しパターンを含む場合、RegExpはindexOfよりも高速になる場合があります。コメントと@Felixの回答を参照してください。


しかし、これは他の方法とどのように比較されますか?これは最速ですか、それともそれを行う多くの方法の1つにすぎませんか?
Chii

これはJavaScript自体によって実装されるため(つまり、ネイティブコードを実行するため)、高速である必要があります。JavaScriptコードに基づく他のメソッドはすべて遅くなります。正確な文字列がわかっている場合は、正規表現の方が少し速いかもしれません(JavaScriptエンジンがプロトタイプチェーンを調べて.indexOfを見つける必要がないため)。
Stephen Chung

大文字と小文字を区別しない検索が必要な場合は、必ずRegExpオブジェクトを作成してを呼び出す必要がありますtest
Stephen Chung

3
Safariでテストを実行しただけです。indexOf他のどの方法よりも遅い等級です。したがって、実際にはどちらの方法が速いかはわかりません。ブラウザによって異なります。
Felix Kling、2011年

@Felix、それは良い観察です(実際に自分で試すまでは絶対に信用しないでください)。繰り返しパターンの多い文字列で言うことを漠然と覚えています。正規表現はステートマシンにコンパイルされ、単純なループよりもはるかに速くバックトラックできるため、単純なループ比較の実装よりも高速に実行する必要があります。次の文字に進みます。実験を行い、これを引き出すための+1!
Stephen Chung

17

最速

  1. (ES6)に含まれる
    var string = "hello"、
    substring = "lo";
    string.includes(substring);
  1. ES5以前のindexOf
    var string = "hello"、
    substring = "lo";
    string.indexOf(substring)!== -1;

http://jsben.ch/9cwLJ

ここに画像の説明を入力してください


8

ES6では、このincludes()メソッドを使用して、1つの文字列が別の文字列内で見つかるかどうかを判断し、返されるtruefalse、必要に応じて返します。

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

ここにjsperfがあります

var ret = str.includes('one');

そして

var ret = (str.indexOf('one') !== -1);

jsperfで示した結果のように、どちらもうまく機能しているようです。


インクルードの引数として「正規表現」を内部で使用できますか?のように:str.includes("x|y"); 同じ呼び出しでリテラル「x」または「y」を検索します。
ptkato

@Patrick、インクルードドキュメントごとに、regexそれを使用することはできません。あなたの質問に対する1つの回避str.includes("x") || str.includes('y')

Chrome 59 JavaScriptの改善の結果、indexOfよりも大幅に高速になっていますincludes(1600%以上高速)。4400万反復/秒と7億7700万 i /秒の違いが実際のパフォーマンスにどのように影響するかは不明ですが、モバイルindexOfは、理想的な選択であるはずの十分な利益をもたらす可能性があります。
Chad Levy

7

単純なforループを使用して、文字列内のすべての要素を反復処理し、を使用して比較するとcharAtindexOfまたはよりも高速に実行されることがわかりましたRegex。コードと証明はJSPerfで入手できます

ETA:indexOfcharAtの両方jsperf.comに記載されているブラウザスコープデータに応じてクロムモバイルに同様にひどい行います


不思議なのは、組み込みの機能よりも手作りの機能のほうが優れていることですが、これは、針が1文字であるためと考えられます。それでも...
モス14

Apple iPad(iOS 7.1.1)上のChrome Mobile 36.0.1985.57でテスト済み。IndexOfの方が高速です。申し訳ありません
rpax 2014

@rpax CharAtは、すべてのプラットフォームで(jsperfの履歴に基づいて)かなり高速ですが、Chromeモバイルは例外で、IndexOfとCharAtの両方のパフォーマンスは、デスクトップに比べて非常に低くなっています。
wpg4665

1
NodeJSでこれがどのように機能するかを確認したいのですが、部分文字列ではなく1文字しか検索していないので、これは実際には良い例ではありません。
qodeninja 2014年

これはまったく有効な答えではありません。部分文字列を検索するのではなく、1つの単一文字の出現のみを検索します
Henrik Myntti

3

単純な文字列を見つけるための、のindexOf()メソッドを使用して正規表現を使用することはほとんど同じです:http://jsperf.com/substring -ので、書き込みに簡単に思える今まで一つは選択してください。



1

これは、.match()メソッドを使用して文字列を作成する簡単な方法です。

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

良い一日でありますように


4
メソッドmatchが存在する理由はありませんtest…一番上の答えを確認してください。
ベルギ2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.