C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: Collection Dictionary について


(過去ログ 171 を表示中)

[トピック内 16 記事 (1 - 16 表示)]  << 0 >>

■98608 / inTopicNo.1)  Collection Dictionary について
  
□投稿者/ VBA初心者 (1回)-(2021/12/07(Tue) 11:29:06)

分類:[.NET 全般] 

エクセルの VBA を使っています。
初心者ですみません。

タイトル通りなのですが、Collection と Dictionary の
違いが判りません。

ネットの記述やサンプルを見ても、どちらも同じにしか思えません。

new で初期化するか、CreateObject で初期化するかの違いと
Collection は Key を省略できるぐらいの違いしか判りませんでした。

もともとやりたかったことは
C#で dicdata = new Dictionary<string,List<string>>(); なのですが、
これをすることが Collection と Dictionary でできるのかどうかも
わかりませんでした。

VBAのCollection と Dictionaryではやりたいことができないのでしょうか?
引用返信 編集キー/
■98609 / inTopicNo.2)  Re[1]: Collection Dictionary について
□投稿者/ KOZ (186回)-(2021/12/07(Tue) 12:08:03)
2021/12/07(Tue) 12:53:37 編集(投稿者)

No98608 (VBA初心者 さん) に返信
> タイトル通りなのですが、Collection と Dictionary の
> 違いが判りません。

Collection はリスト、Dictinary は連想配列です。

Collection の構造については、ここが参考になるかも。

「Microsoft.VisualBasic.Collection」
https://source.dot.net/#Microsoft.VisualBasic.Core/Microsoft/VisualBasic/Collection.vb

.NET の List<T> はリストといいながら中身は配列だったりするのですが(^_^;)

「System.Collections.Generic.List<T>」
https://source.dot.net/#System.Private.CoreLib/List.cs

> もともとやりたかったことは
> C#で dicdata = new Dictionary<string,List<string>>(); なのですが、

Dictionary の要素として Collection を格納する感じですね。
扱いが面倒になるので独自のコレクションクラスを作ると便利かと思います。

「VBA ほぼタイプセーフなコレクション」
https://qiita.com/tomochan154/items/9dd43fa04a8073f7c6f3

引用返信 編集キー/
■98610 / inTopicNo.3)  Re[1]: Collection Dictionary について
□投稿者/ くま (48回)-(2021/12/07(Tue) 12:55:46)
「dictionary collection 違い」で検索すると結構解説が見つかりますが。

Collection オブジェクト
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/collection-object
Dictionary オブジェクト
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/dictionary-object

配列とCollectionとDictionary の使い分け
http://blog.livedoor.jp/minus_alpha/archives/4233055.html

VBAでCollectionとdictionaryを使う
https://qiita.com/pregum/items/071f72969d72d90cf826

・Collectionオブジェクト
Dictionarより早い
追加位置を指定できる。
KeyはString型のみ
後から値の変更ができない

・Dictionaryオブジェクト
キーの変更を行ったり、またキーが重複していないか確かめるメソッドがある
あとKeyのみ値のみの配列を取得する事が可能。
これによりKeyの値によるソートなどが作りやすい

> dicdata = new Dictionary<string,List<string>>(); なのですが、
使用する用途になりますが、可能です。
次にサンプルを用意したので確認してどの組み合わせが良いか選んでみてください。
引用返信 編集キー/
■98611 / inTopicNo.4)  Re[2]: Collection Dictionary について
□投稿者/ くま (49回)-(2021/12/07(Tue) 12:56:20)
2021/12/07(Tue) 13:00:47 編集(投稿者)
Function Test()
    ' Collectionの場合
    Dim MyClasses1 As New Collection
    MyClasses1.Add "item1", "key1"
    MyClasses1.Add "item2", "key2"
    Debug.Print MyClasses1("key1")
'    MyClasses1("key1") = "item1-E" 'エラーになる
'    Debug.Print MyClasses1("key1")
    
    ' Dictionaryの場合
    Dim MyDictionary1
    Set MyDictionary1 = CreateObject("Scripting.Dictionary")
    MyDictionary1.Add "key1", "item1"
    MyDictionary1.Add "key2", "item2"
    Debug.Print MyDictionary1("key1")
    MyDictionary1("key1") = "item1-E"
    Debug.Print MyDictionary1("key1")

    ' Collectionの場合キーがString以外だとエラーになる
'    Dim MyClasses2 As New Collection
'    MyClasses2.Add "item1", 1
'    MyClasses2.Add "item2", 2
    
    ' Dictionaryの場合キーがString以外でもOK
    Dim MyDictionary2
    Set MyDictionary2 = CreateObject("Scripting.Dictionary")
    MyDictionary2.Add 1, "item1"
    MyDictionary2.Add 2, "item2"

    ' Collectionの中にCollectionを追加
    Dim MyClasses3 As New Collection
    MyClasses3.Add New Collection, "key1"
    MyClasses3.Add New Collection, "key2"
    MyClasses3("key1").Add "item1-1", "key1-1"
    MyClasses3("key1").Add "item1-2", "key1-2"
    MyClasses3("key2").Add "item2-1", "key2-1"
    MyClasses3("key2").Add "item2-2", "key2-2"
    Debug.Print MyClasses3("key1")("key1-1")
    Debug.Print MyClasses3("key2")("key2-2")
    'MyClasses3("key2")("key2-2") = "item2-2-E" 'エラーになる
    'Debug.Print MyClasses3("key2")("key2-2")

    ' Dictionaryの中にDictionaryを追加
    Dim MyDictionary3
    Set MyDictionary3 = CreateObject("Scripting.Dictionary")
    MyDictionary3.Add "key1", CreateObject("Scripting.Dictionary")
    MyDictionary3.Add "key2", CreateObject("Scripting.Dictionary")
    MyDictionary3("key1").Add "key1-1", "item1-1"
    MyDictionary3("key1").Add "key1-2", "item1-2"
    MyDictionary3("key2").Add "key2-1", "item2-1"
    MyDictionary3("key2").Add "key2-2", "item2-2"
    Debug.Print MyDictionary3("key1")("key1-2")
    Debug.Print MyDictionary3("key2")("key2-2")
    MyDictionary3("key2")("key2-2") = "item2-2-E"
    Debug.Print MyDictionary3("key2")("key2-2")

    Dim arrayVal() As Integer
    
    ' Collectionの中に配列を追加、ただし配列の要素数変更が直接できない
    Dim MyClasses4 As New Collection
    ReDim arrayVal(0 To 1)
    arrayVal(0) = 0
    arrayVal(1) = 1
    MyClasses4.Add arrayVal, "key1"
    ReDim arrayVal(0 To 2)
    arrayVal(0) = 2
    arrayVal(1) = 3
    arrayVal(2) = 4
    MyClasses4.Add arrayVal, "key2"
    Debug.Print MyClasses4("key1")(0)
    Debug.Print MyClasses4("key2")(0)
    MyClasses4("key2")(0) = 10
    Debug.Print MyClasses4("key2")(0) '値の変更はされない

    ' Dictionaryの中に配列を追加、ただし配列の要素数変更が直接できない
    Dim MyDictionary4
    Set MyDictionary4 = CreateObject("Scripting.Dictionary")
    ReDim arrayVal(0 To 1)
    arrayVal(0) = 5
    arrayVal(1) = 6
    MyDictionary4.Add "key1", arrayVal
    ReDim arrayVal(0 To 2)
    arrayVal(0) = 7
    arrayVal(1) = 8
    arrayVal(2) = 9
    MyDictionary4.Add "key2", arrayVal
    Debug.Print MyDictionary4("key1")(0)
    Debug.Print MyDictionary4("key2")(0)
    MyDictionary4("key2")(0) = 20
    Debug.Print MyDictionary4("key2")(0) '値の変更はされない

    ' Collectionの中にDictionaryを追加
    Dim MyClasses5 As New Collection
    MyClasses5.Add CreateObject("Scripting.Dictionary"), "key1"
    MyClasses5.Add CreateObject("Scripting.Dictionary"), "key2"
    MyClasses5("key1").Add "key1-1", "item1-1"
    MyClasses5("key1").Add "key1-2", "item1-2"
    MyClasses5("key2").Add "key2-1", "item2-1"
    MyClasses5("key2").Add "key2-2", "item2-2"
    Debug.Print MyClasses5("key1")("key1-1")

    ' Dictionaryの中にCollectionを追加
    Dim MyDictionary5
    Set MyDictionary5 = CreateObject("Scripting.Dictionary")
    MyDictionary5.Add "key1", New Collection
    MyDictionary5.Add "key2", New Collection
    MyDictionary5("key1").Add "item1-1", "key1-1"
    MyDictionary5("key1").Add "item1-2", "key1-2"
    MyDictionary5("key2").Add "item2-1", "key2-1"
    MyDictionary5("key2").Add "item2-2", "key2-2"
    Debug.Print MyDictionary5("key1")("key1-2")


End Function


引用返信 編集キー/
■98612 / inTopicNo.5)  Re[2]: Collection Dictionary について
□投稿者/ 貴婦人 (2回)-(2021/12/07(Tue) 13:16:47)
VBAのCollectionはハッシュテーブルだったような
Scripting.Dictionaryもハッシュテーブル
機能的には変わらない

性能はデータ量次第かな
私なら要素数が10000件以内ならDictionary
それ以上ならCollectionと使い分ける

Dictionaryはテーブルサイズが固定のようで要素数が1万を超えたあたりから計算量が急激に悪化するんだよね

C#と同じことができるかについては値にリストを格納するだけなのでどちらでもできると思う、リストは自作するなり配列で代替するなりmscorelibのArrayListを使うなりすれば良い



引用返信 編集キー/
■98613 / inTopicNo.6)  Re[3]: Collection Dictionary について
□投稿者/ KOZ (187回)-(2021/12/07(Tue) 13:37:41)
2021/12/07(Tue) 13:38:04 編集(投稿者)
No98612 (貴婦人 さん) に返信
> VBAのCollectionはハッシュテーブルだったような

正しくはキーをハッシュテーブルで管理したリスト、かなぁ

Sub CollectionTest()
    Dim c As New Collection
    Dim i As Long
    Dim v As Long
    
    For i = 1 To 100000
        c.Add i, "k" & i
    Next
    Debug.Print Now
    
    For i = 1 To 100000
        v = c("k1")
    Next
    Debug.Print Now
    
    For i = 1 To 100000
        v = c("k100000")
    Next
    Debug.Print Now

    For i = 1 To 100000
        v = c(1)
    Next
    Debug.Print Now

    For i = 1 To 100000
        v = c(100000)
    Next
    Debug.Print Now

End Sub

c(100000) のアクセスが異常に遅いです。

引用返信 編集キー/
■98614 / inTopicNo.7)  Re[1]: Collection Dictionary について
□投稿者/ 魔界の仮面弁士 (3244回)-(2021/12/07(Tue) 13:46:08)
No98608 (VBA初心者 さん) に返信
> タイトル通りなのですが、Collection と Dictionary の
> 違いが判りません。

順序を重視するのが Collection
キー指定が前提なのが Dictionary

後者は「.Add key, item」で、
前者は「.Add item, key」なのが紛らわしい。


VBA.Collection
 ・アイテムの順序を維持しているコレクション
 ・Key 無しでも Key 有りでも使える
 ・挿入位置を指定した登録も可能
 ・組み込みのオブジェクトなので追加の参照設定が不要(CreateObject は使わない)
 ・すべてのメンバーがメソッド(代入用プロパティなどは無い)
 ・アイテムの差し替えはできないが、削除 & 再挿入で代用可能
 ・Key を指定する場合、Key は文字列でなければならない
 ・Key のみを列挙する機能は無い
 ・Key の存在有無をチェックできない(エラートラップでの代用は可能)
 ・Key の大文字小文字は区別されない


Scripting.Dictionary
 ・Key 指定が必須なコレクション
 ・挿入位置を指定した登録は出来ない
 ・New する場合は参照設定が必要(CreateObject による生成も可能)
 ・アイテムを差し替え可能なプロパティを持つ
 ・Key のみ、あるいは値のみの列挙が可能
 ・Key の大文字小文字を区別することも区別しないこともできる
 ・Key の存在有無をチェックできる
 ・Key は文字列でなくても良い(オブジェクトでも可)

ArrayList
 ・アイテムの順序を維持しているコレクション
 ・Key 指定機能は無い
 ・挿入位置を指定した登録は出来ない
 ・New する場合は参照設定が必要(CreateObject による生成も可能)
 ・要素のサブセットを取り出すことができる
 ・要素の順序を昇順または降順に並べ替える事が出来る


> C#で dicdata = new Dictionary<string,List<string>>(); なのですが、
Set dicData = New VBA.Collection
dicData.Add Split("VB C# VBA VBS"), "Language"

とかですかね。配列ではなく Collection でも良いですが。

dicData.Add New VBA.Collection, "Language"
dicData!Language.Add "VB"
dicData!Language.Add "C#"
dicData!Language.Add "VBA"
dicData!Language.Add "VBS"

もちろん Dictionary でも可。
引用返信 編集キー/
■98615 / inTopicNo.8)  Re[2]: Collection Dictionary について
□投稿者/ くま (50回)-(2021/12/07(Tue) 14:07:15)
みなさんお詳しいので...参考までに
CollectionとDictionaryでのループ取得方法の違いサンプルです。
ただ自分も気のなったのが

・Collection
追加位置を指定できるぐらいだから追加順は保持される。

・Dictionary
調べると追加順は保持される・されないの2通りが出てくる。
自分の経験だと「追加順が保持されない」事がない
(キーのみ取得しても追加順)
こちらもキーのみハッシュテーブルで別に持っているって事でしょうかね?

Function Test1()

Dim key As Variant
Dim val As Variant
Dim i As Integer

' Collectionの場合(Key指定なし)
Dim MyClasses1 As New Collection
MyClasses1.Add "item1"
MyClasses1.Add "item2"
MyClasses1.Add "item3"
MyClasses1.Add "item4"
MyClasses1.Add "item5"

'----- For Eachで値を直接取得
For Each val In MyClasses1
Debug.Print val
Next val

'----- 追加位置は保持される
MyClasses1.Add "item2Bef", , 2
For Each val In MyClasses1
Debug.Print val
Next val

'----- itemで取得
For i = 1 To MyClasses1.Count
Debug.Print MyClasses1(i)
Next i

' Dictionaryの場合
Dim MyDictionary1
Set MyDictionary1 = CreateObject("Scripting.Dictionary")
MyDictionary1.Add 1, "item1"
MyDictionary1.Add 2, "item2"
MyDictionary1.Add 3, "item3"
MyDictionary1.Add 4, "item4"
MyDictionary1.Add 5, "item5"

'----- For Eachで値を直接取得
For Each val In MyDictionary1.Items
Debug.Print val
Next val

'----- 追加位置は保持される
MyDictionary1.Add 0, "item0"
For Each val In MyDictionary1.Items
Debug.Print val
Next val

'----- For EachでKeyから取得
For Each key In MyDictionary1.keys
Debug.Print MyDictionary1(key)
Next key

End Function

引用返信 編集キー/
■98617 / inTopicNo.9)  Re[3]: Collection Dictionary について
□投稿者/ 古谷 (22回)-(2021/12/07(Tue) 20:44:05)
No98615 (くま さん) に返信
> ・Dictionary
> 調べると追加順は保持される・されないの2通りが出てくる。
> 自分の経験だと「追加順が保持されない」事がない
> (キーのみ取得しても追加順)
> こちらもキーのみハッシュテーブルで別に持っているって事でしょうかね?

でっすよねーこれ完全にアンドキュメンテッドですけど順序保持されるんですよね
実装的にはOrderedなDictionaryなんでしょうねー
引用返信 編集キー/
■98618 / inTopicNo.10)  Re[4]: Collection Dictionary について
□投稿者/ 魔界の仮面弁士 (3245回)-(2021/12/07(Tue) 22:34:41)
No98617 (古谷 さん) に返信
>> 調べると追加順は保持される・されないの2通りが出てくる。
>> 自分の経験だと「追加順が保持されない」事がない
> でっすよねーこれ完全にアンドキュメンテッドですけど順序保持されるんですよね

ですよねー。

なのにリファレンスを見ると、For Each での列挙順どころか、
Items メソッドが返す配列と Keys メソッドが返す配列が
同じ順序を保証しているかどうかさえ記されていないという。


> 実装的にはOrderedなDictionaryなんでしょうねー

OrderedDictionary な動作であるという前提のもと、
SortedDictionary 相当に並び替える実装例が、
KB246067 にちょこっと書かれている程度で。


KB246067: Sorting a Scripting Dictionary Populated with String Data
https://j.mp/3DwqoYY
>>> Because this information is stored unsorted, enumerating through the array returns information in the order it was stored.
引用返信 編集キー/
■98619 / inTopicNo.11)  Re[5]: Collection Dictionary について
□投稿者/ くま (51回)-(2021/12/07(Tue) 23:54:42)
古谷さん、魔界の仮面弁士さん情報ありがとうございます
長年のモヤッとした感じが晴れました。
あんまり書くと質問者様にご迷惑となるので私はこれで失礼します。
引用返信 編集キー/
■98628 / inTopicNo.12)  Re[6]: Collection Dictionary について
□投稿者/ VBA初心者 (2回)-(2021/12/08(Wed) 10:54:37)
みなさんありがとうございます。
クラスを作ってみようと思いましたが、以下のようになって太刀打ちできません。

クラスモジュールに clsKbnNams を作りました。
その中に Function を作成しました。

Public Function Add(ByVal new_k As String, ByVal new_h As String)

標準モジュールから

Dim kbnnams As clsKbnNams
kbnnams.Add("", "")

としたのですが、kbnnams.Add("", "") が赤色になっています。
実行すると 構文エラー が表示されます。
何がまちがていますか?

入力中は kbnnams. と打つと Add が選択でき、
kbnnams.Add( まで打つと
Add(ByVal new_k As String, ByVal new_h As String)
が表示されます。
なので、スペルミスとかはないと思いますが
引用返信 編集キー/
■98629 / inTopicNo.13)  Re[7]: Collection Dictionary について
□投稿者/ ロッテモナ王 (6回)-(2021/12/08(Wed) 12:15:55)
No98628 (VBA初心者 さん) に返信
エラーメッセージは何と出力されてますか?
それ読んだ方が早いです

> Dim kbnnams As clsKbnNams
> kbnnams.Add("", "")

インスタンスが設定されてないです
カッコを使うときはCallを付けたがいいです

Dim kbnnams As clsKbnNams
Set kbnnams = New clsKbnNams
Call kbnnams.Add("", "")

引用返信 編集キー/
■98630 / inTopicNo.14)  Re[8]: Collection Dictionary について
□投稿者/ ロッテモナ王 (7回)-(2021/12/08(Wed) 12:19:09)
戻り値ないならFunctionよりSubを使ったが良いかもしれないです

引用返信 編集キー/
■98634 / inTopicNo.15)  Re[9]: Collection Dictionary について
□投稿者/ くま (56回)-(2021/12/08(Wed) 18:25:54)
VBA初心者さん

> タイトル通りなのですが、Collection と Dictionary の
> 違いが判りません。

これが皆さんの回答でご理解いただけたら一度こちらを「解決済み」にして

新しく質問
> クラスを作ってみようと思いましたが、以下のようになって太刀打ちできません。
を作ったほうが良いですよ。


引用返信 編集キー/
■98640 / inTopicNo.16)  Re[10]: Collection Dictionary について
□投稿者/ VBA初心者 (3回)-(2021/12/09(Thu) 11:22:03)
みなさんありがとうございます

クラスを使用して、Collection で管理することができました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -