LoginSignup
270
266

More than 5 years have passed since last update.

JavaScriptの文字列マッチングまとめ(indexOf, lastIndexOf)

Last updated at Posted at 2017-02-26

JavaScriptでよく使う文字列マッチングを、その仕組みも含めて解説。

たとえば、以下のような状況で使用できる。

この記事で扱うマッチング


完全一致

以下のような処理で完全一致を実現できる。

完全一致
var string  = 'hoge';
var pattern = 'hoge';
if(string === pattern){
  // 完全一致のときの処理
}

解説
厳密等価演算子===を使用してデータ型も含めて完全一致の比較を行う。
等価演算子==で完全一致処理を行おうとすると、暗黙の型変換が行われて意図せぬ結果になることがあるので、特別な理由がない限りは厳密等価演算子を使用することをオススメ。

JavaScript 忘れがちな === と == の違い


前方一致

以下のような処理で前方一致を実現できる。

前方一致
var string  = 'isogram';
var pattern = 'is';
if(string.indexOf(pattern) === 0){
  // 前方一致のときの処理
}

解説
indexOf()はターゲット文字列内の何文字目でパターン文字列が見つかったのか返す。
0文字目,1文字目,..と数え上げるので、最初の文字で見つかった場合は0が返ってくる。これを利用して前方一致の判定を実現できる。

前方一致のコードを短縮する

前方一致_短縮版
var string  = 'isogram';
var pattern = 'is';
if(!string.indexOf(pattern)){
  // 前方一致のときの処理
}

JavaScriptにおいて数値を論理値に変換したときに0false、それ以外の数はすべてtrueとして扱われる。
つまり、indexOf()は前方一致したときのみfalseと見なされる値を返す、そうでないときはtrueと見なされる値を返す性質を持っている。
これを利用して、indexOf()の結果を否定演算子!により反転すれば短いコードで前方一致の判定ができる。

前方一致で見つかったとき
image

前方一致で見つからなかったとき
image

活用例
目的のクエリパラメタの値を取得するコード - Qiita

ES6バージョンの前方一致

ES6が使える環境なら、startsWith()でOK。

ES6前方一致
var string  = 'isogram';
var pattern = 'is';
if(string.startsWith(pattern)){
  // 前方一致のときの処理
}

部分一致

以下のような処理で部分一致を実現できる。

部分一致
var string  = 'isogram';
var pattern = 'og';
if(string.indexOf(pattern) > -1){
  // 部分一致のときの処理
}

解説

indexOf()ではマッチしなかったとき-1を返す。マッチしたときは0以上の整数を返す。これを利用して部分一致の判定を実現できる。

部分一致のコードを短縮する

部分一致_短縮版
var string  = 'isogram';
var pattern = 'og';
if(~string.indexOf(pattern)){
  // 部分一致のときの処理
}

~は数値をビット反転する演算子であり、「indexOf()でマッチしなかったとき返ってくる数値」である**-1をビット反転した数値は0になる。

0はif文においてfalseと判定され、それ以外の数はすべてtrueとして扱われるため、
これを利用して、indexOf()の結果を~でビット反転すれば短いコードで部分一致の判定ができる。

参考)
(10進数の)数値xをビット反転した値 = -(x + 1)

image

※分かりやすくするために2進数を符号付き4bit整数で表しているが、実際の処理では符号付き32bit整数として処理されている。

部分一致で見つかったとき
image

部分一致で見つからなかったとき
image

よって、
~string.indexOf(pattern)により部分一致が成立する。

活用例
UA情報から電話デバイスかどうかを判定するコード - Qiita
Cookieをオブジェクト形式で取得するJavaScriptコード - Qiita

ES6バージョンの部分一致

ES6が使える環境なら、includes()でOK。

ES6部分一致
var string  = 'isogram';
var pattern = 'og';
if(string.includes(pattern)){
  // 部分一致のときの処理
}

後方一致

以下のような処理で後方一致を実現できる。

後方一致
var string  = 'isogram';
var pattern = 'am';
if((string.lastIndexOf(pattern)+pattern.length===string.length)&&(pattern.length<=string.length)){
  // 後方一致のときの処理
}

解説

lastIndexOf()indexOf()と同じく、パターン文字列が見つかる場所をターゲット文字列の中から探す関数だが、こちらはターゲット文字列の後方から探す。

indexOf()とlastIndexOf()の動作の違い

'aaaa'.indexof('a');  // -> 0
'aaaa'.lastIndexof('a');  // -> 3

「後方から探したときにターゲット文字列が見つかった場所 + パターン文字列の長さ」は、後方一致した場合ターゲット文字数と一致する。

image

ただし、この計算は
「ターゲット文字列の長さ+1 = パターン文字列の長さ」であったときも成立するため、
pattern.length<=string.lengthとなっていることも確認した上で後方一致の判定を行う。

よって、
(string.lastIndexOf(pattern)+pattern.length===string.length)&&(pattern.length<=string.length)により後方一致が成立する。

ES6バージョンの後方一致

ES6が使える環境なら、endsWith()でOK。

ES6後方一致
var string  = 'isogram';
var pattern = 'am';
if(string.endsWith(pattern)){
  // 後方一致のときの処理
}

正規表現による一致

以下のような処理で正規表現による一致を実現できる。

正規表現による一致
var string = 'isogram';
var pattern = /^i\w{2}gra\w?$/;
if(pattern.test(string)){
  // 正規表現一致のときの処理
}

解説

JavaScript - 正規表現のmatchとexec

正規表現をチェックするときに参考になる記事
正規表現チェックツールまとめ


意図せずES6の便利さがよくわかる記事になってしまいました。
ES6を使えば呪文みたいなコードを書く必要がなくなるので、
使える環境ではES6を使っていきたいです。

参考になるリンク
ES6の概要と、最新ブラウザに対応させる「Babel」の使い方 | ES6のある星に生まれて
各種ES6環境構築まとめ(Typescriptもあるよ) - Qiita

270
266
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
270
266