rangeメソッドによる文字列検索
macOS Mojava 10.15.7 / Xcode 11.3.1 / Swift 5.0
rangeメソッドによりテキストを指定したキーワードで検索し、マッチした文字列があれば、それらが先頭から何文字目にあるかを求める。
2種類の rangeメソッド
rengeメソッドは、Stringクラスと NSStringクラスのいずれにも定義されている。
両者とも、文字列の中に指定した文字列があるかどうかを判定し、あればその range(開始位置と文字列の長さ)を返すものだが、
戻り値の型が異なる。
NSStringクラス
戻り値は、NSRangeオブジェクト
Stringクラス
戻り値は、オプショナル型の Rangeオブジェクト
戻り値の型は、NSStringクラスの場合 NSRange構造体に、Stringクラスの場合 Range構造体になる。前者は一目で、「"日本"は、先頭から 5文字目から長さが 2文字」とわかるが、後者はよくわからない。Swiftになってデフォルトの文字列の型が NSStringクラスから Stringクラスに変わってから、rangeメソッドは非常に使い勝手が悪いツールになってしまった。
実用的な対応
検索の結果を NSRangeオブジェクトとして得る方法は2つある。
検索する文字列を NSStringオブジェクトに変換する。
戻り値の Rangeオブジェクトを NSRangeオブジェクトに変換する。
検索を繰り返す
例題として、対象のテキストの中に検索文字列が複数ある場合の検索方法を考えてみる。rangeメソッドは、テキストの中に検索文字列が複数あっても最初の文字列しか検索しない。すべての文字列を検索したい場合は、文字列の検索範囲を一回の検索ごとにスライドさせながら、rangeメソッドを繰り返し実行していく。
Stringクラスの extensionにメソッドを作成してみた。
指定した検索語でStringオブジェクトを検索し、結果を NSRangeオブジェクトの配列として返す。
検索自体は Stringクラスの rangeメソッドで行う。文字列の検索範囲は range引数により、Indexの範囲として指定する。startIndex、endIndexは文字列の始点と終点を表す値。rangeの upperBoundは検索で合致した文字列の次の文字位置に相当し、検索を繰り返すにつれ upperBoundは終点に向かって移動する。
Stringクラスの rangeメソッドで取得した Rangeオブジェクトは、NSRangeクラスのイニシャライザにより NSRangeオブジェクトに変換する。
実行例
オプション caseInsensitive
半角英字の大文字小文字を区別しない