読者です 読者をやめる 読者になる 読者になる

VBAHaskell ユーティリティ群

VBA

先日の記事でVBAHaskellに数学関数を入れ始めたが、案の定その後が続かず放置状態になっている。とりあえず気にせずにユーティリティ関数群を追加する事にした。既存の関数のシンタックス・シュガーや特定の集計作業を便利にするための関数の寄せ集めだ。(適宜機能を追加していく)

シンタックス・シュガーとはいえ、3つ以上の引数を持つものを2変数にして、
mapF や zipWith、fold/scan 系の関数で使えるようになった ものもある。
モジュール名は「misc_utility」で、GithubおよびHPにある。

関数/Sub 機能 備考
p__n getNth_b(, n)の構文糖 関数オブジェクトのみ
p_typename データ型名 関数オブジェクトのみ
p_p_format Format関数 関数オブジェクトのみ
p_InStr InStr関数 関数オブジェクトのみ
p_InStrRev InStrRev関数 関数オブジェクトのみ
p_foldl1 1次元配列のfoldl1 関数オブジェクトのみ
p_foldr1 1次元配列のfoldr1 関数オブジェクトのみ
p_scanl1 1次元配列のscanl1 関数オブジェクトのみ
p_scanr1 1次元配列のscanr1 関数オブジェクトのみ
subM_R subM(m, 行範囲) の構文糖 p_subM_R を提供
subM_R_b LBound基準のsubM_R p_subM_R_b を提供
subM_C subM(m, , 列範囲) の構文糖 p_subM_C を提供
subM_C_b LBound基準のsubM_C p_subM_C_b を提供
selectRow_b LBound基準のselectRow p_selectRow_b を提供
selectCol_b LBound基準のselectCol p_selectCol_b を提供
(Sub) fillRow_b LBound基準のfillRow
fillRow_b_move LBound基準のfillRow_move
(Sub) fillCol_b LBound基準のfillCol
fillCol_b_move LBound基準のfillCol_move
- - -
adjacent_op 隣接する要素間で2項操作 p_adjacent_op を提供
(Sub) rowWise_change 2次元配列の行ごとに関数適用
rowWise_change_move 2次元配列の行ごとに関数適用 rowWise_change 後に move して返す
(Sub) columnWise_change 2次元配列の列ごとに関数適用
colomnWise_change_move 2次元配列の列ごとに関数適用 columnWise_change 後に move して返す
equal_all 全要素の等値比較 p_equal_all を提供
equal_all_pred 全要素の等値比較(述語版)
- - -
splitStr2Funs 文字列を区切って関数列へマッピング
str2SummaryFun 文字列から集計関数へ変換 group_by_partition_pointsで使用
str2ConvertFun 文字列から型変換関数へ変換
group_by_partition_points 配列のGROUP BY集計 partition_point による

p_foldl1 は、本来の foldl1 に対する関数オブジェクトではない。
foldl1は引数を3つ持つので VBAHaskell の関数オブジェクトにすることはできない。3つ目の引数はどの次元を畳み込みの軸にするかを指定している。ここでは2引数の foldl1_v という関数を実装し、それに対する関数オブジェクトとして定義している。畳み込みの軸は指定できないので1次元配列に対象が限定されるが、通常はこれで十分だと思う。
subM_RsubM_C も同様に用途を行・列に限定することで関数オブジェクトにできるようにした(p_subM_R、p_subM_C)。

adjacent_op は今までなかったタイプの関数で、隣り合うペアを関数の引数にした結果を並べる。n個の要素を持つ配列であればn-1個の要素を持つ配列が出力される。

colomnWise_change_move は2次元配列の列ごとに関数を適用して変更するもので、たとえば特定の列をString型から整数型に変換するなどに使える。
その際、適用関数の列を作らなければならないが、それをサポートするのが文字列を区切って関数列へマッピングする splitStr2Funs だ。これを使ってC言語のprintfのように"%d%d%s"といった指定が可能になる。

group_by_partition_points は GROUP BY 的な集計作業をするものだ。SQLの GROUP BY はグループを分けるカラムを決め、それ以外の集計対象カラムに対する集計方法(SUMとか)を指定する機能を持っていると思う。この関数はグループ分けをする機能は持っておらず、グループの切れ目の位置は引数で与える必要がある代わりに、全部の列が集計対象カラムになる。切れ目の位置は、Haskell_5_sortモジュールにある partition_points(またはpartition_points_pred)関数などで作ることを想定している。

' 30行6列の配列を作る(値はランダム整数)
m = makeM(30, 6, uniform_int_dist(30*6,1,8))
' 昇順ソートしておく
m = subM(m, sortIndex(m))
' 最初の列でグループ分けしたときの切れ目の位置をを求める
pp = partition_points(selectCol(m, 0))
' その切れ目でグループ分けして集計(先頭、サンプル数、SUM, Average, MIN, MAX)
g = group_by_partition_points(m, pp, "%t%c%s%a%min%max")

どういう集計をするかは3番目の変数に文字列で指定するようにした。
「% + 特定文字」が集計方法を表し、たとえば %s とか %sum が合計値といった感じだ。

集計方法 文字列
先頭の値 %t %tp %top
末尾の値 %b %btm %bottom
個数 %c %cnt %count
合計 %s %sum %計
平均 %a %avg %average
最大 %max
最少 %min

この指定には上記 splitStr2Funs を使っているが、自分で変換関数を定義することによってもカスタマイズできる。

GithubのUtilityモジュール
HPのUtilityモジュール