C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

コレクションのバブルソートをお借りする

前回が今年の最後にするつもりだったのですが、気になる事があったので
これを最後にします。

VBAでコレクションや配列をソートしたい場合基本的には無く、単調なものであれば
DotNetArrayListを利用する事も考えるのですが、ちょっと単調ではない
条件(プロパティで とか)でソートする場合、ゴリゴリ書くしか方法がやはり無いん
ですね。

非常に参考になったのがこちらのt-hom'sさんのサイト

http://thom.hateblo.jp/entry/2015/11/29/212934

これを流用させてもらおうと思ったのですが、案の定CATIAのApplicationクラス
にはRunメソッド無いんですよ・・・。


好み的な部分も有り、こんな感じにしてみました。
(データが整数って言うのが、無意味に近いのですが)

'vba Collection_BubbleSort_Test

Sub Collection_BubbleSort_Test()
    Const Min = 1& '最小値
    Const Max = 100& '最大値
    Const Count = 10& '数
    
    Dim lst As Collection: Set lst = New Collection
    Dim i&
    For i = 0 To Count
        lst.Add Fix((Max - Min + 1) * Rnd + 1)
    Next
    
    Debug.Print "-- Before --"
    Call Dump(lst)
    Debug.Print "-- Aafter --"
    Call B_Sort_List(lst)
    Call Dump(lst)
    Debug.Print "-- End --"
End Sub

'ソート条件 True-降順 False-昇順
Private Function Comparison(ByVal A As Variant, ByVal B As Variant) As Boolean
    Comparison = A > B
End Function

'BubbleSort_Collection
Private Sub B_Sort_List(ByRef List As Collection)
    Dim i&, j&
    For i = 1 To List.Count
        For j = List.Count To i Step -1
            If Comparison(List(i), List(j)) Then
                    CollectionSwap List, i, j
            End If
        Next j
    Next i
End Sub

'Collection用スワップ
Private Sub CollectionSwap(ByRef List As Collection, ByVal Idx1&, ByVal Idx2&)
    Dim Item1, Item2
    With List
        If IsObject(.Item(Idx1)) Then
            Set Item1 = .Item(Idx1)
            Set Item2 = .Item(Idx2)
        Else
            Let Item1 = .Item(Idx1)
            Let Item2 = .Item(Idx2)
        End If
        .Add Item1, After:=Idx2
        .Remove Idx2
        .Add Item2, After:=Idx1
        .Remove Idx1
    End With
End Sub

'Debug
Private Sub Dump(ByVal lst)
    Dim l
    For Each l In lst
        Debug.Print l
    Next
End Sub

キモは、Comparison関数です。バブルソート内の IF文 で、True か False を返す
関数さえ作ってしまえば良いのかな? と思いました。
上記では昇順ですが、降順にしたい場合はComparison関数内を

    Comparison = A < B

に、するだけです。

但し、t-hom'sさんのサンプルほど汎用性が無いんです。複数の異なる条件でソート
したい場合は、NGなんです・・・。

それを考えると Ariawase の Funcクラスを利用し

Private Sub B_Sort_List(ByRef List As Collection, ByVal fun As Func)
 ・・・

の様にし、ソート条件用の関数さえ用意しておけば、異なる条件化で
ソート出来る様になるんじゃないのかな? と思ったりしてます。(未確認です)
悩む・・・。 良いお年を。