【Swift5】SwiftでNgramを実装する

Contents

はじめに

私が受講しているプログラミング学習スクールRareTECHでNgramを実装してみようという課題があり、Swiftで挑戦したところ見事に撃沈したので調べて実装してみました。

 

以下のバージョンで実行しています。

- Xcode: Version 13.2.1 (13C100)
- Swift: 5.5.2

Ngramとは

コトバンクでは以下のように定義されています。

任意の文字列や文書を連続したn個の文字で分割するテキスト分割方法.特に,nが1の場合をユニグラム(uni-gram),2の場合をバイグラム(bi-gram),3の場合をトライグラム(tri-gram)と呼ぶ.最初の分割後は1文字ずつ移動して順次分割を行う.

イマイチピンと来ないので例を用いて説明します。

Ngramの例

「吾輩は猫である」を例にしてみます。

N = 1のとき

"吾", "輩", "は", "猫", "で", "あ", "る"
1文字ずつ区切られます。

N = 2のとき

"吾輩", "輩は", "は猫", "猫で", "であ", "ある"

区切りの先頭の文字を1文字ずつずらしながら、2文字ずつ区切っていきます。

N = 3のとき

"吾輩は", "輩は猫", "は猫で", "猫であ", "である"

N = 2と同様ですが今度は3文字ずつ区切っています。

実装

処理のフローを考えてから実装に入ります。

処理のフロー

    1. 分割する文字列(input)と何文字毎に分割するかの整数値(n)を受け取る。
    2. 取り出した文字列を格納するための配列(sentence)を宣言する。
    3. inputの先頭のindexを定義しておく。
    4. inputの文字数 - n 回ループする(最後の要素のindexは文字数-nにしないと範囲外にはみ出てしまう)
    5. 取り出す文字の先頭の文字のindexを定義。
    6. 取り出す文字の末尾の文字+1のindexを定義。
    7. 指定した範囲で文字列を取り出す。
    8. 取り出した文字列をsentenceに追加する。
    9. sentenceを返却or出力する。

実際のコード

実装のポイント

 

for文のループを回す回数は文字数 - n回

分割する文字のindexとnの関係について考えてみるとわかりやすいです。

 

吾[0] 輩[1] は[2] 猫[3] で[4] あ[5] る[6]

 

[]内は要素のindexです。

indexの数は文字数 -1 になります。

n = 2のときは最後の「ある」の先頭の文字の「あ」のindexは5であり、文字数 7 - n(2)になります。

n = 3のときは最後の「である」の先頭の文字の「で」のindexは4であり、文字数 7 - n(3)になります。

 

Swiftの文字列操作について

Swiftの文字列操作に苦戦しました。
文字列操作については別記事にまとめたいと思います。

 

おわりに

私の理解が甘く、間違った情報を記載している部分があるかもしれません。
また上記の実装よりもよりよい実装があるかと思います。
誤りなどありましたらご指摘いただけましたら幸いです。

参考資料

Swift 実践入門 増補改訂第 3 版
https://kotobank.jp/word/N%E3%82%B0%E3%83%A9%E3%83%A0-1702302
https://chusotsu-program.com/swift-string-slice/

Twitterでフォローしよう

おすすめの記事