[Swift] String を1行毎に処理する方法

     
⌛️ 2 min.

String を1行づつ処理する方法を説明します。

環境&対象

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

  • macOS14.5 Beta
  • Xcode 15.3
  • iOS 17.4
  • Swift 5.9

String と行数

Swift の String は、文字の集合という形で定義されています。


参考
StringApple Developer Documentation

つまり、そのままでは、行数という概念はありません。改行コードも含めた文字の集合が String です。

ちなみに、改行コードとしては、以下の2つで定義されています。
文字としては、CharacterSet.newlines と CharacterClass.newlineSequence の2つで定義されています。

CharacterSet は、String 周りの メソッドで使用されていて、CharacterClass は、RegexBuilder と合わせて導入 struct です。RegexBuilder 周りのメソッドは、CharacterClass が使用されています。


参考
CharacterSet.newlinesApple Developer Documentation


参考
CharacterClass.newlineSequenceApple Developer Documentation

いわゆる、”\n” や “\r” 等が上記の定義に含まれています。

行毎に分割してから処理する

1行づつ処理する方針の1つは、String を1行づつに分割して、配列になった [String] を処理することです。

string.split を使って、分割する(改行文字指定)

行毎に分割する方法の1つは、改行文字を指定して、String を分割し、その後処理することです。


参考
split(separator:maxSplits:omittingEmptySubsequences:)Apple Developer Documentation

例えば、改行コードが “\n” であることがわかっている場合は、以下のように、改行文字を指定して分割することができます。

MEMO

split メソッドは 指定文字で String を分割するメソッドなので、改行文字以外でも 指定文字で分割することができます。

import Foundation

let string = """
             Hello
             World

             a
             """

let lines = string.split(separator: "\n")

print(lines)
// print-out
["Hello", "World", "a"]

空行を無視するかどうかのオプション(omittingEmptySubsequences)がデフォルトで true のため、World と a の間の空行が破棄されています。

string.split を使って、分割する(RegexBuilderを使って)

CharacterClass に定義されている newlineSequence を使用して、String を分割することもできます。


参考
split(separator:maxSplits:omittingEmptySubsequences:)Apple Developer Documentation

このメソッドは、指定された CharacterClass に含まれる文字を使って、String を分割したものを返してくれます。

import Foundation
import RegexBuilder

let string = """
             Hello
             World

             a
             """

let lines = string.split(separator: CharacterClass.newlineSequence)

print(lines)
// print-out
["Hello", "World, "a"]

このメソッドでも分割後に空行となったものを無視するオプション(omittingEmptySubsequences)が デフォルトで true のため、World と a の間の空行は削除されたものが返されています。

分割しつつ処理する

1行づつ処理する方針のもう1つは、String を1行づつに分割しながら処理することです。

この方針の良い点は、処理途中でも 判断によって処理を終了することができる点です。

MEMO

どの文字を改行と判断するかについては、ドキュメントには記載されていませんが、おそらく、Unicode で定義されているものと同じだと推測します。(CharacterSet.newlines や CharacterClass.newlineSequence と同じということです)

string.enumerateLines を使って、処理する

String で用意されているメソッドの1つに、enumerateLines というものがあります。


参考
enumerateLinesApple Developer Documentation

これは、String を行毎に分割して、与えられた closure を呼び出してくれるものです。

import Foundation
import RegexBuilder

let string = """
             Hello
             World

             a
             """

string.enumerateLines(invoking: { line, stop in
    print("\(line)")
})
// print-out
Hello
World

a

空行を無視するオプションはありませんので、closure 内で必要に応じて処理することが必要です。

MEMO

closure に渡されてくる文字列は改行文字が削除されたものです。

2つめの引数(この例では stop) に true をセットして closure を終えると その行を処理したところで、enumerateLines は処理を終えます。
以下では、World という行が見つかった時に、終了するようにしています。

import Foundation
import RegexBuilder

let string = """
             Hello
             World

             a
             """

string.enumerateLines(invoking: { line, stop in
    print("\(line)")
    if line == "World" { stop = true }
})
// print-out
Hello
World

まとめ

String を1行毎に処理する方法まとめ

String を1行毎に処理する方法まとめ
  • split を使うと改行文字で分割できる
  • split を使う方法として、改行文字を直接指定する方法と CharacterClass で指定する方法がある
  • enumerateLines をつうと、1行毎の処理を書くことができる

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

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

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

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

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

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

コメントを残す

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