CSVの解析とその技法(状態遷移と先読み)

10
ほえほえ@スプシマン @hoehoe1234

②で作成する関数は、Jag配列を作成することになると思います。なのでシートに展開するために③のヘルパー関数などを作るとより便利に使えるかと思います。④は標準的な使い方を事例として提示するような感じになると思います。

2021-04-23 04:39:43
ほえほえ@スプシマン @hoehoe1234

これで、それぞれのパートの責務が明確になりますので、イレギュラーなCSVに対してもどのパートでどう対応するのかの作戦が立てやすくなると思います。

2021-04-23 04:40:31
ほえほえ@スプシマン @hoehoe1234

CSVの1行をRFCに沿って状態遷移で解析する手法。状態遷移表を「そのまま」コードにおとしています。コードだけでは一見意図がわかりませんが設計図である状態遷移表をみれば明確に意図が分かります。 pic.twitter.com/Zu5YuLd3YA

2021-04-24 14:28:01
拡大
ほえほえ@スプシマン @hoehoe1234

状態遷移表です。この遷移表で予めデバックを行うのでコードの修正は比較的少なくなります。 pic.twitter.com/3l1foG4YUI

2021-04-24 14:30:12
拡大
ほえほえ@スプシマン @hoehoe1234

アクションについては関数ではなくgosubを使って実装しました。状態遷移技法とgosubはとても相性がよいですね。gosubルーチンをアクションとして利用することでこちらも状態遷移表をそのまま実装できます。 pic.twitter.com/gdQTCZLPD6

2021-04-24 14:42:00
拡大
ほえほえ@スプシマン @hoehoe1234

状態遷移については、エラー部分が多いので処理を簡潔に書こうと思えば書けますが、これは修正を入れるときに却ってわかりにくくなります。特殊な処理を入れる場合に制御構造を変更しなけいけなくなるのはよくないので状態遷移を素直に表現したコードのほうがよいでしょう。

2021-04-24 14:48:19
ほえほえ@スプシマン @hoehoe1234

制御ロジックファーストが普通なんだけど(それがアルゴリズムだから)、そうではなくて状態を外側にするとコードは見にくくなるけど保守性の良い、実はわかるととても読めるコードになります。

2021-04-24 17:03:18
ほえほえ@スプシマン @hoehoe1234

状態遷移でかく最大のメリットは「変更容易性」でしょう。ロジックでは頭からかんがえなおしですが、状態遷移では状態さえ変わらなければ簡単に変更できます。

2021-04-24 17:04:18
ほえほえ@スプシマン @hoehoe1234

状態遷移+先読み手法は、ガチで必須技法なのでおおくひとに知ってほしい。CSVがこんなに簡単に解析できることを知ってほしい。イレギュラー対応も「とても入れやすい」ということがわかってもらえると思います。

2021-04-24 17:06:01
ほえほえ@スプシマン @hoehoe1234

状態遷移は制御構造に先に状態があります。ですから巧妙なコード(アルゴリズムが先)にくらべて冗長になりがちですが、保守性はかなり高くなります。もっともわかりやすい利点は「独自の処理の挿入」でしょう。処理を変更するポイントが状態遷移コードでは明白になる場合がおおいです。

2021-04-24 17:22:40
ほえほえ@スプシマン @hoehoe1234

状態遷移でかくことにより、たとえばCSVの解析では区切り文字列を指定する場合もコードを変更する必要はありません(元コードに足りないところを追加しています)。カンマ区切り、タブ区切り、その他の区切りのどのような区切り文字にもシームレスに対応できます。 pic.twitter.com/XsOKmOMeBn

2021-04-24 17:30:02
拡大
ほえほえ@スプシマン @hoehoe1234

CSV解析ルーチン群のパイプラインイメージ。各パイプライン(関数)は個別に作りドライバ関数でつなげるイメージ。これにより多くの問題が局所化、特化され多様なCSVに対応できる関数群になります。 pic.twitter.com/YNJOvudyGc

2021-04-26 22:20:18
拡大
ほえほえ@スプシマン @hoehoe1234

CSVのレールロードダイアグラム。終端記号(1つのトーン)と非終端記号(終端記号/非終端記号で構成される上位の記号)を簡易的に作成してみました。 pic.twitter.com/KeVGuLgKB4

2021-04-26 22:22:05
拡大
ほえほえ@スプシマン @hoehoe1234

作成した元ネタはこちらです。多段パイプにしているので項認識関数ではrecord以下の文法を認識すればよいことになります。 pic.twitter.com/FfnjDwJXr9

2021-04-26 22:23:39
拡大
ほえほえ@スプシマン @hoehoe1234

この各非終端記号を関数として呼び出す構造にしてもよいのですが、CSVの文法は相互再帰が不要なので1つのレールロードダイアグラムに展開しました。 pic.twitter.com/Y6o8H3yBrX

2021-04-26 22:25:56
拡大
ほえほえ@スプシマン @hoehoe1234

レールロードダイアグラムで文法を記述できたら、次は状態遷移(図または表)に直します。状態番号は分岐が発生(図上は赤色)する箇所に番号を割り振ります。分岐時に「1文字またはもう1文字」読み込むことで分岐が決定できる必要があります。 pic.twitter.com/XJcDgqawvb

2021-04-26 22:38:31
拡大
ほえほえ@スプシマン @hoehoe1234

モジュール構成はこのようになります。設計で多段階に分けたので、データ構造を介した疎結合となっています。これは各モジュール(関数)を個別に扱え、他の関数と組み合わせ可能なことを意味します。 pic.twitter.com/BumBqlCbio

2021-04-26 22:42:07
拡大
ほえほえ@スプシマン @hoehoe1234

たとえばline_make関数はファイルからの入力を想定していますが、CSVファイルに特殊なルールがある場合などはここで対応したり、ファイル以外の入力(なかなか想定できませんが)に差し替えたりできます。

2021-04-26 22:43:47
ほえほえ@スプシマン @hoehoe1234

arr_make関数はシート用に2次元配列作成を想定していますが、この部分もほしい出力に合わせて他のモジュールに差し替えることができます。疎結合はデータ構造を介して結合しているのでこのようなことが可能になります。

2021-04-26 22:44:49
ほえほえ@スプシマン @hoehoe1234

これを1つのモジュールで制御構造密結合で作成すると特有な関数となり変更容易性が失われます。しかし、代わりに性能と簡潔性が得られます。どう組み立てるかは環境次第ですが、ライブラリであれば疎結合、ユーザ・コードで再利用しないのであれば密結合がよいでしょう。

2021-04-26 22:46:59
ほえほえ@スプシマン @hoehoe1234

エクセル+VBAでは ①制御構造密結合 ②データ構造密結合(シートを介して結合) ③疎結合(データ構造を介して結合) が選択できます。関数オブジェクト、ジェネレータ等は使えません。用途に応じて使い分けるとよいと思います。

2021-04-26 22:48:26
ほえほえ@スプシマン @hoehoe1234

CSV1行解析(term_make関数)に誤りがありました。黄色の部分が修正部分となります。ここを「error」としていたため空項目でエラーが発生していました。 pic.twitter.com/TFuNn894Io

2021-04-26 22:55:02
拡大