[Swift] String の範囲指定を理解する (String/Range, NSString/NSRange)

     
⌛️ 2 min.
前回、String/NSString で 文字列中の位置を表す String.Index と Int についてまとめましたので、今回は、部分文字列を表現する Range と NSRange についてまとめます

[Swift] String の位置指定を 理解する(String/String.Index と NSString/Int)

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterey 13 Beta3
  • Xcode 14.0 Beta3
  • iOS 16.0 beta

部分文字列

文字列処理として、文字列の一部を抜き出したり、置き換えたりということをすることがあります。

そのような時に、変更対象である 文字列の一部を指定することが必要となります。

文字列中の範囲指定には、 String 向けには Range<String.Index> が、NSString 向けには、NSRange が使用されます。

部分抜き出し操作

文字列の部分文字列を抜き出すためには、開始位置と終了位置指定が必要です。

この開始位置(と終了位置指定)で、前回説明した、位置情報が使用されます。

Range は、開始/終了位置の情報が必要です。

NSRange には、開始位置と文字列長の情報が必要となります。

Range/NSRange

String/NSString の一部は、文字列中の範囲として表現され それぞれ Range/NSRange を使って指定することができます

Range

String の範囲を表現するためには Range<String.Index> が使用されます。

Range は、String 向けに特別に作られた型ではありません。

Apple のドキュメントは、こちら

数学的にいうと、半開区間を表現するための型です。

例えば、Double を使って、0 から 10まで(ただし10を含まない)という範囲を表すには、Range 型を使用して、以下のように書きます。
数学的には [0,10) と書く区間を表しています。


let range: Range<Double> = 0..<10
range.contains(0)    // -> true
range.contains(10)   // -> false

この場合の半開区間とは、0 を含み、(10を含まない)直前までの区間ということです。
ですので、contains という Range に含まれるかを判定するメソッドの結果が、0 は true ですが、10 は false になっています。

このように、Range は、連続している要素の区間を表す型です。

文字列の Index も、(その文字列の文字にそって)連続していますので、文字列中の範囲を、この Range を使用して表現することができます。

なお、String 中の範囲を表現する時に Range が使用するのは、String.Index です。

ですので、String では、Range<String.Index> を使用して区間を表現します。

NSRange

NSString の範囲を指定するには、NSRange が使用されます。

Apple のドキュメントは、こちら

NSRange として見つかるのは上記ですが、実際には、こちらを見る方がわかります。

NSRange は、位置情報と長さ情報を組み合わせて記録しています。

位置情報、長さ 共に、Int で指定します。

Range 的な、開始位置・終了位置という形での情報としては、lowerBound/upperBound というプロパティが用意されています。
lowerBound/upperBound を使用した initializer もあります。

なお、NSRange も NSString 専用ということではなく、連続した情報を表現することができます。区間の共通部分を計算したりということも可能です。

部分文字列関連操作

抜き出し

文字列から、その文字列の 一部文字列を抜き出す操作です。

“Hello world!” から “Hello” を抜き出したりということです。

String での部分文字列抜き出し

String は、subscript で Range を指定することで、指定範囲の文字列を抜き出すことができます。
Apple のドキュメントは、こちら


let text: String = "012345"
let index1 = text.index(after: text.startIndex)
let index4 = text.index(text.startIndex, offsetBy: 4)
let substr = text[index1..<index4])
print(substr)
// print-out
123

NSString での部分文字列抜き出し

NSString では、substring というメソッドを使用して、NSRange 指定で部分文字列を抜き出します。
Apple のドキュメントは、こちら


let nsStr: NSString = "012345"
let pos1 = 1
let nsSubstr = nsStr.substring(with: NSRange(location: pos1, length: 3))
print(nsSubstr)
// print-out
123

削除

文字列から指定範囲の文字列を削除することもできます。

“Hello world!” から “world” を削除して、”Hello !” としたりすることです。

String での部分文字列削除

String で 文字列の一部(部分文字列) を削除するには、removeSubrange メソッドを使います。

Apple のドキュメントは、こちら


var text: String = "012345"
let index1 = text.index(after: text.startIndex)
let index4 = text.index(text.startIndex, offsetBy: 4)
text.removeSubrange(index1..<index4)
print(text)
// print-out
045

NSString での部分文字列削除

NSString で 文字列の一部を削除するには、NSMutableString の deleteCharacters(in:) メソッドを使います。

# NSString は、immutable つまり 変更できない文字列を表すオブジェクトなので、変更したければ NSMutableString を使う必要があります。

Apple のドキュメントは、こちら


let nsStr: NSMutableString = "012345"
let nsRange = NSRange(location: 1, length: 3)
nsStr.deleteCharacters(in: nsRange)
print(nsStr)
// print-out
045

置き換え

指定範囲の文字列を 別の文字列に置き換える操作もあります。

String での部分文字列置き換え

String で 指定範囲の文字列を別の文字列に置き換えるには、replaceSubrange メソッドを使用します。

Apple のドキュメントは、こちら

以下の例のように、置き換える長さは、置き換える文字列長と一致している必要はありません。


let text: String = "012345"
var text2 = text
let index1 = text2.index(after: text.startIndex)
let index4 = text2.index(text.startIndex, offsetBy: 4)
text2.replaceSubrange(index1..<index4, with: "Hello")
print(text2)
// print-out
0Hello45

NSString での部分文字列置き換え

NSString で 指定範囲の文字列を別の文字列に置き換えるには、replacingCharacters メソッドを使用します。

Apple のドキュメントは、こちら


llet nsStr: NSMutableString = "012345"
let nsRange = NSRange(location: 1, length: 3)
nsStr.replaceCharacters(in: nsRange, with: "Hello")
print(nsStr)
// print-out
0Hello45

指定範囲長が0 のケース

replaceSubrange/ replaceCharacters で与えた範囲の長さが0の場合、単純に指定位置に文字列を挿入することになります。


var text: String = "012345"
let index1 = text.index(after: text.startIndex)
let index4 = text.index(index1, offsetBy: 0)
text.replaceSubrange(index1..<index4, with: "Hello")
print(text)
// print-out
0Hello12345

let nsStr: NSMutableString = "012345"
let nsRange = NSRange(location: 1, length: 0)
nsStr.replaceCharacters(in: nsRange, with: "Hello")
print(nsStr)
// print-out
0Hello12345

置き換え文字列が空文字のケース

replaceSubrange/ replaceCharacters で与えた置き換え文字列が 空文字(“”) である場合、単純に指定範囲が削除されることになります。


var text: String = "012345"
let index1 = text.index(after: text.startIndex)
let index4 = text.index(index1, offsetBy: 3)
text.replaceSubrange(index1..<index4, with: "")
print(text)
// print-out
045

let nsStr: NSMutableString = "012345"
let nsRange = NSRange(location: 1, length: 3)
nsStr.replaceCharacters(in: nsRange, with: "")
print(nsStr)
// print-out
045

まとめ

String と Range<String.Index>, NSString と NSRange を使った文字列中の範囲指定をまとめました。

String と Range<String.Index>, NSString と NSRange を使った文字列中の範囲指定
  • String は、Range<String.Index> を使って指定する
  • NSString は、NSRange を使って指定する
  • String には、Range を受け取るメソッドとして、subscript, replaceSubrange, removeSubrange が用意されている
  • NSString/NSMutableString には、NSRange を受け取るメソッドとして、substring, replaceCharacters, deleteCharacters が用意されている

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

最新版を購入するのがおすすめです。

現時点では、上記の Swift 5 に対応した第5版が最新版です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です