ワクワクV057回目配列完全解説3回目(2021-09-18)

配列,VBA,エクセル,
1
ほえほえ@スプシマン @hoehoe1234

ワクワクV057回目(2021-09-18)の画像キャプチャーのみUPしてみます。雰囲気だけでも伝われば。実際の講義については動画をご覧ください。(キャプチャは時間順です)。 pic.twitter.com/U4iKVsBIBJ

2021-09-20 23:56:54
拡大
ほえほえ@スプシマン @hoehoe1234

画像だけでは伝わらなさすぎなので少しだけコメントを。Jag配列を作ったり、表示したりしています。 pic.twitter.com/2MhScsS87g

2021-09-20 23:57:39
拡大
ほえほえ@スプシマン @hoehoe1234

jag配列はおもしろいですね。このあたりの記法は辞書、コレクションとは挙動が少し違います。(x)(y)で直接アクセスできるのはいいですね。 pic.twitter.com/9cyUr2FjJa

2021-09-20 23:58:41
拡大
ほえほえ@スプシマン @hoehoe1234

これからわかるように、VBAでは下限がきまってないのでほんといろいろ大変ですね。 pic.twitter.com/nPEOV9Wvbn

2021-09-21 00:00:00
拡大
ほえほえ@スプシマン @hoehoe1234

配列をエレガントに扱うための基礎的な関数をつくってみます。ここでからの配列のUboundが-1なのが効いてきますね。 pic.twitter.com/Gx7U0zKvUa

2021-09-21 00:01:24
拡大
ほえほえ@スプシマン @hoehoe1234

実装はこれでよいのですが、 要素数=上限ー下限+1 だけ覚えておけば十分ですね。実際は 上限=下限+要素数-1 で計算されています。 pic.twitter.com/E0TYd7VGm8

2021-09-21 00:02:59
拡大
ほえほえ@スプシマン @hoehoe1234

内容が固定のjag配列を作っていますが、append関数を作るだけで見違えるようにエレガントな記法になってしますね。これは配列の上限、下限という実装詳細が隠蔽されて、「配列に追加」という抽象機能に置き換わっているからです。なので「読みやすく」なります。 pic.twitter.com/duRxc1gM41

2021-09-21 00:04:39
拡大
ほえほえ@スプシマン @hoehoe1234

この考え方はとても重要で、「上限を1つ上に変更して空いたところに要素を追加する」というコードからappendで「最後に要素を追加する」という抽象化が行われています。後者にすることで頭にいれる情報がすくなくてすみます。なので抽象化するんですね。

2021-09-21 00:05:53
ほえほえ@スプシマン @hoehoe1234

要素が1つ追加できれば、今度はそれを下請け関数にして「配列に配列を追加する関数」、extend関数をエレガントに実装することができます。これ以上ないシンプルさですね。これが関数の組み合わせ方の方法論の一つです。抽象概念を組み合わせていくんですね。 pic.twitter.com/OJNDIrMGmV

2021-09-21 00:07:37
拡大
ほえほえ@スプシマン @hoehoe1234

この辺は、しっておけば便利かな?というトリックですね。 pic.twitter.com/6t1QxoTF3l

2021-09-21 00:08:22
拡大
ほえほえ@スプシマン @hoehoe1234

制限はありますが、通常の使用ではこれで十分でしょう。件数がおおくなればtranspose相当の自作関数を作る必要がありますが。 pic.twitter.com/4WUFd3k3jZ

2021-09-21 00:09:15
拡大
ほえほえ@スプシマン @hoehoe1234

これは最重要ですね。2次元配列のイテレーション(要素を順番に見る)は8方向あるのですがその手順を①~④で示しています。これに限らず、手順を考える時はホワイトボードが威力を発揮します。(図中、xとyに一部使用間違いがあります。すみません)。 pic.twitter.com/zuqdUKjNpx

2021-09-21 00:10:49
拡大
ほえほえ@スプシマン @hoehoe1234

手順① Jag配列のイメージ図を書く。1次元配列から各要素配列につながっているイメージ。そしてそのイメージ図に変数を割り当てます。この場合はxとyを使用しています。 手順② 一般アクセス式に変数を割り当てます。jag配列の一般アクセス式はjag(x)(y)となります。

2021-09-21 00:12:57
ほえほえ@スプシマン @hoehoe1234

手順③ 具体的に書きます。まず出したい数字を順番通りに書きます。今回は1,4,7,10,2,3・・・とjag配列をあえて横順で出力します。そして、具体的な数字にxとyの値を記入します。(1,1),(2,1),(3,1),(4,1),(1,2)・・・となりますね。この具体をめんどくさがらずに記入するのが大切です。

2021-09-21 00:15:24
ほえほえ@スプシマン @hoehoe1234

手順④ 具体例がわかりましたので今度は二重ループに変換します。後から変わるほうが外側(アウター)ループになり、先に変わるほうが内側(インナー)ループになりますね。ですから今回はyがアウター、xがインナーループになることがわかります。

2021-09-21 00:16:52
ほえほえ@スプシマン @hoehoe1234

ここまでくればあとはx,yのそれぞれのループを下限を意識して記述すればよいということになります。手順をまとめると簡単ですね。この手順をめんどぐさがらずに一度は行うことが大切です。慣れれば頭の中でできますから。

2021-09-21 00:18:21
ほえほえ@スプシマン @hoehoe1234

この手順を理解しておくと、Jag配列のようなものでも4済からの2方向イテレーション、すなわち8方向イテレーションを迷わずにループを書くことができます。これが手法の偉大なところです。一見難しそうですが手順を追うと実に簡単なのです。追加演習を出しておきました。jagでなく2次元配列です。 pic.twitter.com/pdsH8gaUG1

2021-09-21 00:20:30
拡大
ほえほえ@スプシマン @hoehoe1234

演習12ですが、動的配列に対して、バリアント変数にバインドする動的変数はどう言えばいいんでしょうね。ワイはとりあえず「バリアントバインド配列」って読んでますが決まった呼び方はあるのでしょうか? pic.twitter.com/JixEZy1W4z

2021-09-21 00:21:52
拡大
ほえほえ@スプシマン @hoehoe1234

演習13です。append関数があれば瞬殺ですね。このように関数で行うは共通化というよりも「抽象概念をそのまま書けるようにする」みたいな感覚なんです。これですとarray(1,2,3)をループでappend関数呼び出すだけですね。 pic.twitter.com/supDcPYNLy

2021-09-21 00:23:24
拡大
ほえほえ@スプシマン @hoehoe1234

もちろん処理の共通化もあるのですが、ライブラリを作っていて意識するのは処理の抽象化なんですよね。どうしてこれが重要かというと、使うときに「抽象化概念をそのままコードにできる」ってことなんですよね。書きたい概念にマッチする関数がそのままある。ってことを目指しています。

2021-09-21 00:24:35
ほえほえ@スプシマン @hoehoe1234

Jag配列の解説です。画像のコピー時間などにより順番がいろいろですがご容赦ください。赤色にあるように、Jag配列の要素の配列はレコード型として使用する場合があります。VBAではユーザ定義構造体がバリアントに格納できないのでその代案ですね。ちょっと悲しいですが。 pic.twitter.com/qtFwq7SCTY

2021-09-21 00:26:15
拡大
ほえほえ@スプシマン @hoehoe1234

演習14です。配列に配列を追加する関数、extend関数の実装演習です。append関数とextend関数のたった2つの関数だけでVBAの配列が見違えるように使いやすくなりますね。これは操作の抽象化を行ったからです。 pic.twitter.com/RNQxg1zbIu

2021-09-21 00:27:45
拡大
ほえほえ@スプシマン @hoehoe1234

これは割と有名な話ですが、配列の要素のメモリ上での配置順です。ループとfor eachでは取り出す順番が縦横違いますね。その理由を解説しています。 pic.twitter.com/9v0S4vVFUz

2021-09-21 00:29:05
拡大
ほえほえ@スプシマン @hoehoe1234

配列の要素は図右のように配置されています。配列のfor eachはメモリ上の順番どおりに出しているんですね(これはイテレータの実装依存と思われる)。実際にメモリをダンプしてこのように並んでいることは確認済みです。 pic.twitter.com/IlRFJi1zT7

2021-09-21 00:31:10
拡大
ほえほえ@スプシマン @hoehoe1234

配列の最終次元しかredimで変更できない理由もわかりますね。最終次元ではメモリの移動はありません(管理情報の変更のみ)が、それ以外の次元ではメモリの移動を伴います。出来なくもありませんがそれは禁止した設計にしたのでしょうね。

2021-09-21 00:32:12