構造体配列の複数キーソート

解決


ケロロ2等兵  2005-04-27 08:51:03  No: 89601

いつもお世話になっております。ケロロです
今回mdbでテーブルの書き換えをしないといけなくなりまして
その作業中なのですがテーブルが増えすぎてきまして
自分なりにもうすこしスマートにできないかと思いまして
構造体配列の使用にいたりました。
この構造体中身は
・idno(文字型)
・rankupdate(日付型)
となっておりまして、まずrankupdate、idnoのソート順にしないといけません
がみようみまねで構造体配列を扱っておりましてrankupdate順にはならべられたのですが(もうひとつ構造体配列をもうけまして)
同日づけのidno順のソートがうまくいきません
過去ログに一件あったのですがわかりませんでしたし、ググッったりしても「構造体  配列  ソート」とかで調べてもそのものといのはなかったので
教えていただければと思います
またひとつの構造体配列だけでそんなものはできるといわれるかもしれないので
もしそんな方法があるのでしたら教え手いただけないでしょうか?
お願いします  それでは


ねろ  2005-04-27 17:46:21  No: 89602

rankupdate + デリミタ  + idno と言う文字列を作り、
構造体 -> ー次元文字列の配列  -> ソート  ->  構造体に戻す
という具合にすれば簡単な様に思いますが。


Say  2005-04-27 21:40:40  No: 89603

オンメモリレコードセットに放り込んでソートするとか。


ケロロ2等兵  2005-04-27 22:59:21  No: 89604

さっそくのお返事ありがとうございます
ねろさん>
自分はロジックにこだわりすぎてそんなことに考えつきませんでした
すみません
大変勉強になりました
Sayさん>
早急にごくの意味を調べます(汗)

今回自分にもすぐにできそうなので
ネロさんの案でやらせていただきます
それで回答もらってもうしわけないんですが
構造体配列の複数キーソートというのはのちのち必要になってくると思いますので
教えていただけたらと思うのですが
もちろんこれからはそういうのはつかうことはまずないというご指摘でしたら
肝に銘じてもおきたいので
よろしくお願いします


ねろ  2005-04-27 23:54:50  No: 89605

もともとVBには単純なソートの関数さえ存在しません。
ましてユーザー定義型となると。。。。
多次元配列のソート関数を自分で作るしか有りません。
ただしいくら頑張っても、VBで作るソートは遅いですよ。
なぜ文字列のソートを勧めたのかと言いますと、データーベースと言うことで
データーがかなり大きいと想像されたからです。
文字列にしてファイルに落としてしまえばDOSのSortコマンドが使えるからです。
たとえば下のコードは10万件のソートを、一瞬でやってしまいます。

Option Explicit
Private Type db
    idno As String
    rankupdate As Variant
End Type
Dim mdbdata(100000) As db
Private Sub Form_Load()
    Dim i As Long
    Dim File1 As String, File2 As String
    Dim FileNo
    '------テストデーターの作成--------------------------
    For i = 0 To UBound(mdbdata) - 1
        mdbdata(i).idno = Format(CStr(i), "0000000000") 'サンプルのデーター
        mdbdata(i).rankupdate = Date + (i \ 10)         'サンプルのデーター
    Next
    '----------------------------------------------------
    File1 = App.Path + "\" + "test1.txt"  'ソート前
    File2 = App.Path + "\" + "test2.txt"  'ソート後
    FileNo = FreeFile
    Open File1 For Output As #FileNo
    For i = 0 To UBound(mdbdata) - 1
        Print #1, mdbdata(i).rankupdate & "," & mdbdata(i).idno 'データー結合
    Next
    Close
    'ソート
    Shell Environ("ComSpec") & " /c  sort /r <" & Chr(34) _
        & File1 & Chr(34) & " > " & Chr(34) & File2 & Chr(34)
End Sub


ケロロ2等兵  2005-04-28 08:51:42  No: 89606

ご面倒おかけします。回答ありがとうございます。

追加での優先事項・追加項目がでてしまいまして
実装がすこし遅れがちになっております
結果がでしだいソース等のせますのでもうしばらくおまちください
会社環境でないとちょっと無理な感じで
というか自分でサンプルデータとかみようみまねでできないというのがなさけないですが

Sayさん>
けっこうオンメモリレコードセットの発言されてますね
調べ物したらお名前をなんどか拝見しましたし
これって構造体配列とオンメモリってどっちがはやいんでしょうね
ADOって仮装テーブルみたいなのつくれるんですね
DAOにはないのでしょうか探したらみあたらなかったもので(会社で作ってる分が以前からDAOのためどっちかというとDAOよりになっております)
おかげでまたひとつ語句をしりました

ねろさん>
mdbファイル自体は約300Mです。
でそのうちの会員用のテーブルが1万件
で昇格関係のプログラムなので
そういった昇格の系列みたいなものが3万件くらい
といった感じですが
実際昇格でソートが必要になる部分というのは将来かなり楽観的にみても40もないというのが現状です
その中のソートになるので特に心配はないかなっと思ってます
ただいろいろソートが複雑になりそうな気配はあります
たとえば今回の文字列にしても日付(降順)、会員番号(昇順)とかになるとやっぱりむずかしそうですし(単純に自分の脳みそがたりてない感はもちろんあります)
ということでロジックを勉強したいと思ったしだいであります
ここのログにも前にありましたけどそのログを読み解く力が自分にはなかったので
ソート関係の本を買ったら構造体配列の複数キーのやり方とかすこしはのってますかね
DOSの扱い方まで教え手いただきましてありがとうございます
自分にもうごかせて素人に近いものですから感動しています
このsortコマンドもっとなにかやれないかとかもちょっと調べてみます

それでは


ケロロ2等兵  2005-05-12 08:58:55  No: 89607

遅くなってすみません
とりあえずこんな感じになっています
変な書き方ですみません
結局要望がひとつ追加になったので3つのフィールドをつなげてソートしました

配列追加分
ReDim Preserve idno_h(lp3)
idno_h(lp3).idno = rst.Fields("idno").Value
idno_h(lp3).rankupdate = DMax("rankupdate", "昇格履歴", "kairank = 2 and idno = " & "'" & rst.Fields("idno").Value & "'")
idno_h(lp3).rankup_rank = 3
idno_h(lp3).TreeType_sort = idno_h(lp3).rankup_rank & " " & CStr(idno_h(lp3).rankupdate) & " " & idno_h(lp3).idno
lp3 = lp3 + 1

ソート
For i3 = LBound(idno_h) To UBound(idno_h) - 1
For j3 = LBound(idno_h) To LBound(idno_h) + UBound(idno_h) - i3 - 1
                            If idno_h(j3).TreeType_sort > idno_h(j3 + 1).TreeType_sort Then
                                lvarBuf = idno_h(j3).idno
                                idno_h(j3).idno = idno_h(j3 + 1).idno
                                idno_h(j3 + 1).idno = lvarBuf
                                lvarBuf = idno_h(j3).rankup_rank
                                idno_h(j3).rankup_rank = idno_h(j3 + 1).rankup_rank
                                idno_h(j3 + 1).rankup_rank = lvarBuf
                                lvarBuf = idno_h(j3).rankupdate
                                idno_h(j3).rankupdate = idno_h(j3 + 1).rankupdate
                                idno_h(j3 + 1).rankupdate = lvarBuf
                                lvarBuf = idno_h(j3).TreeType_sort
                                idno_h(j3).TreeType_sort = idno_h(j3 + 1).TreeType_sort
                                idno_h(j3 + 1).TreeType_sort = lvarBuf
                            End If
                        Next j3
                    Next i3


ケロロ2等兵  2005-05-12 09:03:59  No: 89608

すみません間違えました
ソート分
For i3 = LBound(idno_h) To UBound(idno_h) - 1
      For j3 = LBound(idno_h) To LBound(idno_h) + UBound(idno_h) - i3 - 1
            If idno_h(j3).TreeType_sort > idno_h(j3 + 1).TreeType_sort Then
                  lvarBuf = idno_h(j3).TreeType_sort
                  idno_h(j3).TreeType_sort = idno_h(j3 + 1).TreeType_sort
                  idno_h(j3 + 1).TreeType_sort = lvarBuf
            End If
      Next j3
Next i3
お返事くださった方どうもありがとうございました
まだまだ先は長そうですけど、この調子でがんばりたいと思います


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加