今回はパスカル記法を単語ごとに区切って配列で返す関数を作成する。
前回このような記事を書いたのだが、
thom.hateblo.jp
この記事を受けて@Dev_Clipsさん(サイト)からツイッターで「ImageMsoの"名前"の一致率も類似画像抽出に使えそう」とのヒントを貰ったためだ。
さて、ImageMSO画像のファイル名はパスカル記法になっている。
パスカル記法とは、英単語を並べる際、単語の始まりをすべて大文字にしてスペースを入れずにくっつけた形。
例) ThisIsAPascalNotation
今回作成するのはこれを単語単位に分割し、配列に格納するための関数である。
SplitPascal関数と名付けよう。
まぁただコード書いて終わりではあんまりなので、今回は作成プロセスを追って紹介するスタイルで書く。
くどいほど少しずつ組み立ててみよう。
Functionプロシージャの組み立て方がいまひとつ難しいという方の参考になれば幸いである。
1) 枠組みを作る
Function SplitPascal() End Function
2) 引数、戻り値を決める
今回は文字列を渡すのでString型の引数を一つだけ。
Function SplitPascal(expression As String) End Function
戻り値は今回Variant型にするので何も書かない。
3) 戻り値を返す処理を書く
戻り値の型はVariantであるが、そこに含める中身は配列なので、配列型でret変数を作ってとりあえずそれを返す処理にする。
Function SplitPascal(expression As String) Dim ret() SplitPascal = ret End Function
ここまでが定石。どのようなFunctionでもこの流れで作れるのでマスターしよう。
あとは戻り値であるretをどう作りこんでいくかである。
4) 1文字ずつループさせるための、枠組みを作る
1文字ずつ検査して大文字かどうかを見る必要があるので、とりあえず文字数分ループ。
Function SplitPascal(expression As String) Dim ret(), i For i = 1 To Len(expression) '処理 Next SplitPascal = ret End Function
5) 1文字ずつ切り出してプリントしてみる
このあと文字を切り出して、検査・加工するのだが、その前にとりあえず動作がわかるようにプリント文にしておく。
Function SplitPascal(expression As String) Dim ret(), i For i = 1 To Len(expression) Debug.Print Mid(expression, i, 1) Next SplitPascal = ret End Function
6) 呼び出してみる
メインコードを書いて呼び出してみる。まだ戻り値も何も使わないけど、とりあえず1文字ずつプリントされるところまで確認。
Sub Main() SplitPascal "ThisIsAPascalNotation" End Sub
7) 大文字かどうかの判定
ここで文字コードの知識が活きる。といってもコードは知らなくても大丈夫。A~Zが連番になってることを知ってれば、Asc関数とIf文で切り出した文字がA~Zの範囲に収まっているか調べられる。
Function SplitPascal(expression As String) Dim ret(), i For i = 1 To Len(expression) Dim char: char = Mid(expression, i, 1) If Asc("A") <= Asc(char) And Asc(char) <= Asc("Z") Then Debug.Print "★" End If Debug.Print char Next SplitPascal = ret End Function
このとき、大文字だったら★をプリントしたのち、charを出力。大文字でなければcharだけ出力される。
イミディエイトはこんな感じ。
さて、ここで閃いた。これ、一文字ずつ出力しているが、★をスペースに置き換えて一つの文字列に足していったらどうか。
8) スペース区切りで出力
retを配列ではなくてただのString型に変更し、ここに結果文字列を足しこんでいく。
Function SplitPascal(expression As String) Dim ret As String, i For i = 1 To Len(expression) Dim char: char = Mid(expression, i, 1) If Asc("A") <= Asc(char) And Asc(char) <= Asc("Z") Then ret = ret & " " End If ret = ret & char Next SplitPascal = ret End Function
メインコードは戻り値を出力する形に変更。
Sub Main() Debug.Print SplitPascal("ThisIsAPascalNotation") End Sub
すると、イミディエイトウインドウに「 This Is A Pascal Notation」と出力される。
このままでは先頭に1つスペースが入ってるうえ、当初の目的である配列で返すってのができていない。
9) 最後の仕上げ
まあここまで来ればあとは簡単。
余計なスペースの件はTrim関数で解決するし、配列になってない件はSplit関数で解決する。
ということで、戻り値の代入部分をちょっといじるだけ。
Function SplitPascal(expression As String) Dim ret As String, i For i = 1 To Len(expression) Dim char: char = Mid(expression, i, 1) If Asc("A") <= Asc(char) And Asc(char) <= Asc("Z") Then ret = ret & " " End If ret = ret & char Next SplitPascal = Split(Trim(ret)) End Function
メインコードも配列を処理するよう変更
Sub Main() Dim word For Each word In SplitPascal("ThisIsAPascalNotation") Debug.Print word Next End Sub
出力結果はこちら
This Is A Pascal Notation
以上で完成。
ただ当初の目的であったImageMSOへの応用はあまり芳しくなく。。
なんか名前ベースで探しても毛色の違うアイコンが結構ヒットするので苦労中。