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

VBAHaskellの紹介 その8 (ソート関連)

VBA

ソート関連は別にHaskellぽくない。特徴と言えるのは任意の比較関数が使えることくらいだ。

関数は8つ、Subがひとつある。

sortIndex                   昇順ソート後のインデックス配列
sortIndex_pred          任意の比較関数によるソート後のインデックス配列

permutate (Sub)           配列をソートインデックスを使って実際にソートする
lower_bound              ソート済み配列からのキーの検索
lower_bound_pred     ソート済み配列からのキーの検索
upper_bound             ソー済み配列からのキーの検索
upper_bound_pred     ソー済み配列からのキーの検索
equal_range               ソー済み配列からのキーの検索
equal_range_pred      ソー済み配列からのキーの検索

個々の機能は分かると思うので、多少注意を要する点だけあげる。

1.  sortIndexとsortIndex_predは対象配列を直接ソートするわけではなく、下図の赤文字部分にあたるソート後のインデックスを出力する。*1 sortIndexは昇順ソートであり、降順指定はない。*2

対象配列           :    3 , 1,  5 ,  2      ->     1  ,  2   ,  3 ,   5
インデックス    :   [0   1   2    3]      ->   [ 1     3      0     2 ] 

2. ソートした結果の配列を得たいときには、subM関数 *3 を使う。

' 配列を m をソートしたい
index = sortIndex(m)      ' または index = sortIndex_pred(m, comp)

result = subM(m, index)                 ' 昇順
result = subM(m, reverse(index))    ' 降順

3. 対象配列は1次元か2次元のみであり、自動的に判別される。2次元の場合は行をレコードと見たソートであり、列方向のソートはできない。ソートキーはsortIndex関数の第2引数に指定することが可能で、優先したい順に列番号を並べる。省略した場合には全列がキーとなる(左にあるほうの列が優先)。

' 2次元配列 m の0列目, 2列目, 4列目 をソートキーにする

sortIndex(m, Array(0, 2, 4))

4. sortIndex_pred では2引数の比較関数を与えることによって自由な順序でソートできる。この比較は「第1引数が第2引数より小さい」とき1を、そうでないとき0を返すものとする。比較関数さえ書ければいいので、型がバラバラでもジャグ配列でもソートできる。test_module にそのようなテスト関数を追加した。(Function comp000とSub sortTest)

「比較関数を書けばその通りにソートできて当然ではないか」というのが通常の感覚だと思うが、VBAではなかなかできなかった。

2次元配列を対象とする場合は1行を一つの配列とみて比較関数を書く。

5. upper_bound と upper_bound_pred の返り値、そしてequal_range と equal_range_pred の返り値の2番目の要素は検索範囲の最後の要素の「次の」インデックスである。C++の<algorithm>にあるのと同じだ。

6. 残念ながらAPIC++プログラムにコンパイル時処理はない。

 

VBAHaskellの紹介 その7 (bind1stとbind2nd)
http://mmyymmdd.hatenablog.com/entry/2015/04/16/224313

github.com

*1:これに限らず、基本的に関数は副作用を持たないようにしている。

*2:出力されたインデックスを reverse すれば事足りるからだ。

*3:Haskell_4_vectorモジュールにある部分配列を得る関数