http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200603/06030090.txt
を参考にしておりますが、構造体のソートを汎用化する方法がわかりません。
各構造体のFunction CompareToでソートキーをあらかじめ指定するのではなく、「構造体、キーの位置、昇降順指定」をパラメタかグローバル変数に渡して共通関数を使ってArray.Sort()することは可能でしょうか。
それ以外でも汎用的に構造体をソート(できれば複数キー)できれば大丈夫です。どうぞよろしくお願いします。
キーの位置ってなんですか?
> 各構造体のFunction CompareToでソートキーを
ソートの手順を、構造体自体に実装するのではなく、
Dim sorter As New 自作ソートクラス(ソート方法)
Array.Sort(構造体配列, sorter)
のように、Sort メソッドの引数にて指定しては如何でしょう。
たとえば、自作ソートクラスとして
Class StructureSorter(Of T As Structure)
Implements IComparer(Of T)
:
End Class
のようなものを用意しておき、これのコンストラクタにて、
> キーの位置、昇降順指定
をパラメータで指定するような設計にしておけば、あとは
その値を使った IComparer(Of T).Compare を実装することで、
Array.Sort(Of T).Sort(T(), IComparer(Of T)) による並び替えが
行えるかと思います。
ご回答ありがとうございます。
一応作ってみたのですが、何分オブジェクト的な考え方が初心者なものですので次の点についてもう少しお願いします。
(1)構造体要素(と構造体)の指定を可変的にする方法
・DirectCast(x, myStock).DataDate のように固定の場合できましたが、受け取った引数(x番目の要素、または要素名など)による指定方法がわかりません
・(Of T)を使用した場合”DirectCast(x, T).”の状態で選択肢の中に構造体要素が出てこないので、Object型にしています。
(2)Return Compare(DirectCast(x, myStock).Open, DirectCast(y, myStock).Open)
または、Return Compare(CType(x, myStock).DataDate, CType(y, myStock).DataDate)
のように書くと実行途中でキャストのエラーになり、if文の場合動きます。
(3)Array.Sort(Of T).Sort(T(), IComparer(Of T)) の使い方?
※キー固定、構造体固定の例
Public Class class1
Structure myStock
Public DataDate As Date
Public Open, High, Low, Close, Volume As Double
End Structure
Public Class StructureSorter
Implements IComparer
Private jun As Integer '昇順:1、降順:−1
'Private T_obj As Object
Sub New(ByVal AscDsc As Integer)
jun = AscDsc
End Sub
Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
'Return Compare(CType(x, myStock).DataDate, CType(y, myStock).DataDate)
'Return Compare(DirectCast(x, myStock).Open, DirectCast(y, myStock).Open)
If DirectCast(x, myStock).DataDate = DirectCast(y, myStock).DataDate Then
Return 0 * jun
End If
If DirectCast(x, myStock).DataDate < DirectCast(y, myStock).DataDate Then
Return -1 * jun
End If
If DirectCast(x, myStock).DataDate > DirectCast(y, myStock).DataDate Then
Return 1 * jun
End If
End Function
End Class
End Class
sub main
Dim Stock As myStock()
ReDim Stock(10)
・・・・・・
Dim sorter As New StructureSorter(-1)
Array.Sort(Stock, sorter)
end sub
以上よろしくお願い致します
x 番目の要素ってのは要するにフィールドの宣言順で何番目かってことなのかしらん?
場合によってはフィールドが宣言順に並んでない事もあり得るので無理です。
要素名(フィールド名)で指定ってのは、コンパイル解決できないという点で問題を含みます。可能な限りコンパイル時点で問題を防ぐために型というものがあるのですから。
でまあ一般的な解決としては構造体にソート用のパラメータを公開するインターフェイスを実装させる事でしょう。
Structure Implements ICompareParameter な構造体、
IComparer(Of ICompareParameter) な比較子。
// ていうか 48 バイトの構造体……。
そうですね、要素というよりフィールドのことです。
Structure Implements ICompareParameter
IComparer(Of ICompareParameter)
は試してみたいんですが書くとエラーになってしまいます。
難しいですね・・
相談したいのなら、実際にどう書いたかとエラーの内容くらいは書きましょう。独り言なら"チラシの裏"。
ちょっと考えましたが、私が挙げたのじゃ IComparerParameter 配列にしか適用できませんね。
正しくはこんな感じかな。
' 比較する為のプロパティを宣言
Interface IParameter
' 肝心の構造体
Structure Hoge Implements IParameter
' 構造体だけでなくクラスでも
Class Huga Implements IParameter
' 比較関数持ちジェネリッククラス
Class ParameterComparer(Of T As IParameter) Implements IComparer(Of T)
で、
Dim a As Parameter() = { New Parameter(4), New Parameter(2) }
Array.Sort(a, New ParameterComparer(Of Parameter)())
みたいな。
// VB のジェネリクス関連の宣言は、 Of や As は良いアイデアだけど ( ) は分かりづらくなるだけだなぁ……。
| ツイート |
|