|
▼ドカ さん:
こんにちは
ご理解いただけたようでなによりです。
>UO3さんはどうやって、「子Dictionary」なるものが作れると知ることが出来たのでしょうか?
う〜ん、なんとなくです?
この例は、少なからず、掲示板などの回答としてでていますし、回答者さんの中には
「自分が発見した!皆さんもどうぞ」なんてコメントする人もいます。
その人は、本当に、ご自分で発見されたんでしょうし、同じく、私も発見?
Dictionaryに限らず、私の場合は、できる、できないの前に、
「こんなことができたらいいなぁ」とか「こんなふうにやるとできるべきなのになぁ」なんて考えます。
(VBAだけじゃなく、エクセルの操作でも)
で、やってみると、「おっ!できるじゃん」とか「あぁ、やっぱりだめだよね」
最初は、たとえばユーザーフォーム上のコンロロールを配列的に扱うために、
配列を用意して、そこに「クラス」を登録することからはじめたような記憶があります。
(この部分は、参考書に、よく記載されていますので)
で、思考(?)の順序としては
・クラスもオブジェクトだよね
・じゃぁ、配列にその他のオブジェクトをいれられたら、便利かも。
・で、やってみます。結果は「おっ!できるじゃん」です。
・そのあと、Dictionaryの中身の実態も配列だよね。じゃぁ、その中身にDictionaryというオブジェクトを
いれることができれば、そのキーごとの「子Dictionary」を保持することができるんじゃないかな?
・で、やってみます。またまた結果は「おっ!できるじゃん」す。
こんな経緯でしたね。
私は手軽に扱えるので、もっぱら、この方法なんですが、本当のエキスパートさんになると
Dictionaryのデータという「窮屈」な場所をつかうのではなく、私が言う、「子Dictionary」を
「データ保持クラス」といった目的の「クラス」を生成して扱ってらっしゃいますね。
このほうが、どんな形のデータももてますし、データ処理のためのコードすら持てます。
>この記述ですが、本当なのでしょうか?
まず、Dictionary は「かなり速い」ツールです。でも、圧倒的に一番かというと、まずますという
ところなんだろうなと思います。「天才」ではなく「秀才」ですね。もちろん、「秀才」ですから
「並の人」より、光り輝いているんです。
たとえば、以下のサンプルは、きわめて単純なレイアウトをきわめて単純なロジックで扱った場合の
比較です。ほとんど差はありませんが、「秒以下」のところで「ほんの少し」差がでます。
これが、もっともっと複雑なレイアウトで複雑なマッチングロジックになると、極端な場合、
Dictionary処理が1.5倍ぐらいかかるケースもありえます。
・まず、DataGen を実行してください。
これは、結構時間がかかりますけど、がまんしてください。
Sheet1 のA列,B列に50,000行のランダムな値をセットします。
Test1,Test2を実行すると、Sheet1 がかわってしまいますので、比較を公平にするために
1つ実行したら、Sheet2 から セルの内容をSheet1 にコピペしてESCキーでリセットしてから
もう1つを実行してください。
Sub TestGen()
Dim i As Long
Dim x As Long
Dim z As Long
With Sheets("Sheet1")
.Cells.Clear
For i = 1 To 50000
x = Int((1000) * Rnd + 1)
z = Int((100) * Rnd + 1)
.Cells(i, "A").Value = "A" & Format(x, "0000")
.Cells(i, "B").Value = z
Next
.Cells.Copy Sheets("Sheet2").Range("A1")
End With
End Sub
Sub Test1()
Dim dic As Object
Dim c As Range
Dim myTime As Double
myTime = Timer '計測開始
Application.ScreenUpdating = False
Set dic = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
With .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
For Each c In .Cells
If c.Value > dic(c.Value) Then dic(c.Value) = c.Offset(, 1).Value
Next
End With
.Columns("C:D").Clear
.Range("C1").Resize(dic.Count).Value = WorksheetFunction.Transpose(dic.keys)
.Range("D1").Resize(dic.Count).Value = WorksheetFunction.Transpose(dic.items)
End With
Application.ScreenUpdating = True
MsgBox Timer - myTime
End Sub
Sub Test2()
Dim dic As Object
Dim c As Range
Dim myTime As Double
Dim v() As Variant
Dim k As Long
Dim oldkey As Variant
Dim maxNum As Long
myTime = Timer '計測開始
Application.ScreenUpdating = False
With Sheets("Sheet1")
With .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
.Resize(, 2).Sort key1:=.Range("A1"), order1:=xlAscending
ReDim v(1 To .Rows.Count, 1 To 2)
For Each c In .Cells
If c.Value <> oldkey Then
k = k + 1
maxNum = 0
End If
If c.Offset(, 1).Value > maxNum Then maxNum = c.Offset(, 1).Value
oldkey = c.Value
v(k, 1) = oldkey
v(k, 2) = maxNum
Next
End With
.Columns("C:D").Clear
.Range("C1").Resize(k, 2).Value = v
End With
Application.ScreenUpdating = True
MsgBox Timer - myTime
End Sub
|
|