Arrays 证明Excel VBA脚本.Dictionary不保留项插入顺序

Arrays 证明Excel VBA脚本.Dictionary不保留项插入顺序,arrays,excel,dictionary,vba,Arrays,Excel,Dictionary,Vba,我正在尝试决定是否为我的项目使用Excel VBA集合或字典。出于几个原因,我倾向于使用字典,但我在使用For。。每个循环检索字典项或从dictionary items()数组读取项时,检索顺序可能与添加项的顺序不同。这对我的应用程序来说是一个严重的问题,所以我尝试了许多测试用例,试图证明这种顺序不匹配实际上发生了。到目前为止,我还无法创建这样的场景,包括以随机顺序添加和删除项目 任何人都可以提供一个例子来证明检索顺序与Excel VBA脚本.Dictionary的插入顺序不匹配吗?没有人可以提

我正在尝试决定是否为我的项目使用Excel VBA集合或字典。出于几个原因,我倾向于使用字典,但我在使用
For。。每个
循环检索字典项或从dictionary items()数组读取项时,检索顺序可能与添加项的顺序不同。这对我的应用程序来说是一个严重的问题,所以我尝试了许多测试用例,试图证明这种顺序不匹配实际上发生了。到目前为止,我还无法创建这样的场景,包括以随机顺序添加和删除项目


任何人都可以提供一个例子来证明检索顺序与Excel VBA脚本.Dictionary的插入顺序不匹配吗?

没有人可以提供一个对象返回键/项的顺序与添加键/项的顺序不同的例子,因为脚本.Dictionary不这样做。从未。如果以渐进顺序添加以下键/项对,则返回它们的方式就是这样

key  item
 1    A
 2    B
 3    C
 4    D

'enumerate by key
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")

dict.Add Key:=1, Item:="A"
dict.Add Key:=2, Item:="B"
dict.Add Key:=3, Item:="C"
dict.Add Key:=4, Item:="D"

Dim k As Variant
For Each k In dict.Keys
    Debug.Print k & " - " & dict.Item(k)
Next k
您可能指的是简写的“覆盖”方法,即添加密钥而不检查它们是否存在。如果您试图删除一个存在的密钥,将抛出错误457。但是,如果您只是简单地在字典中写入一个新的键和项(如果该键不存在),那么将创建一个新的键和项,但如果该键存在,则该键将保持不变,并且该项将被覆盖

key  item
 1    A
 2    B
 3    C
 4    D
 2    E

'enumerate by key
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")

dict.Item(1) = "A"
dict.Item(2) = "B"
dict.Item(3) = "C"
dict.Item(4) = "D"
dict.Item(2) = "E"     'the second entry's item is overwritten

Dim k As Variant
For Each k In dict.Keys
    Debug.Print k & " - " & dict.Item(k)
Next k
覆盖方法比检查是否存在密钥快一点,但是应该理解其行为。我使用覆盖来有意地检索列表中具有重复键的任何键的最后一项,但这是一种特殊情况。请注意,2并没有超出原始顺序;它只是被后来的那一个取代了

如果已添加Microsoft脚本运行时参考库,则可以在变量声明中使用。这样做的好处是创建速度稍快的dictionary对象并公开其他索引枚举方法

Dim dict As New Scripting.Dictionary

'enumerate by index position (zero-based index)
Dim i As Long
For i = 0 To dict.Count - 1
    Debug.Print dict.Keys(i) & " - " & dict.Items(i)
Next i

'enumerate as elements of an array
Dim a As Long
For a = LBound(dict.Keys) To UBound(dict.Keys)
    Debug.Print dict.Keys(a) & " - " & dict.Items(a)
Next a
fwiw,我发现当字典的值超过有符号整数(32767)时,这个索引枚举不可靠

最后,可以一次删除一个键/项对,也可以一次删除所有键/项对

dict.Remove 2                              'remove by key

dict.Remove dict.Keys(0)                   'remove first key/item by index position
dict.Remove dict.Keys(UBound(dict.Keys))   'remove last key/item by index position

dict.RemoveAll                             'remove all

你在哪里读到的?我会想,在线上有太多关于如何对字典或集合进行排序的帖子,排序顺序是保持不变的,否则为什么还要麻烦排序呢。字典对象上发生的某些神秘活动会改变顺序,这似乎也不合理。谢谢你的回复,但我不会对项目进行任何排序。我只是想知道,如果我添加项目1、2、3、4(按该顺序),那么请阅读a For中的项目。。每次循环,我都得不到1,4,3,2。这是我的观点。如果有那么多人都经历过编写字典排序逻辑的麻烦,那么维持字典顺序是有意义的。否则,排序逻辑将毫无意义。我支持你。我不相信一本字典可以任意地对它的条目重新排序。是合同文件。它没有提到顺序,所以不要假设顺序。谢谢你的信息-我很好奇你所说的“当字典的.Count超过有符号整数(32767)时,索引枚举不可靠”是什么意思?我正在重写字典文档,发现了大量字典键的“不可靠结果”。在我完成更多条件下的测试之前,我无法确定问题所在,因此我使用了“不可靠”一词。你能提供任何你认为不可靠的案例吗?嗯,您可以自己测试这一点,方法是播种大量行,并根据这些行构建键和项的字典,然后将它们返回到同一工作表并进行比较。就我自己的经验而言,在我能够在几个版本的Excel(32位和64位)中重现显示出糟糕结果的经验试验之前,我只会使用“不可靠”一词。如果不经意地声明某些东西在较小的试验台上不起作用,那将是“无响应的”。我最初的流氓结果可能只是一个腐败的环境。。。。并且所有键或项都可以在类似的
中使用。自动筛选字段:=2,标准1:=dict.keys,运算符:=xlFilterValues
。是的,字典是一个强大的工具。