2016-06-08 3 views
2

Я пытаюсь решить, использовать ли Excel VBA Collection или словарь для моего проекта. По нескольким причинам я склоняюсь к словарю, но я продолжаю читать, что при использовании цикла For.. Each для извлечения элементов словаря или при чтении элементов из массива Items() словаря порядок извлечения может быть не порядком добавления элементов. Это было бы серьезной проблемой для моего приложения, поэтому я попробовал много тестовых примеров, пытаясь доказать, что это несоответствие порядка фактически происходит. До сих пор мне не удалось создать сценарий, где это происходит, включая добавление и удаление элементов в произвольном порядке.Докажите, что Excel VBA Scripting.Dictionary не сохраняет порядок вставки элемента

Может ли кто-нибудь предоставить пример, подтверждающий, что порядок поиска не соответствует порядку вставки для Excel VBA Scripting.Dictionary?

+0

Где вы это читал? Я бы подумал с чрезмерным количеством сообщений в Интернете о том, как сортировать словарь или коллекцию, что порядок сортировки поддерживается, в противном случае зачем его сортировать. Также кажется необоснованным, что порядок будет изменен некоторой таинственной деятельностью, происходящей на объекте словаря. – JNevill

+0

Спасибо за ваш ответ, но я не занимаюсь сортировкой предметов. Я просто хочу знать, что если я добавлю элементы 1, 2, 3, 4 (в этом порядке), тогда прочитайте пункты в For .. Каждый цикл, я не получаю 1, 4, 3, 2. – JohnM

+0

Это моя точка хотя. Если так много людей столкнулись с проблемой написания логики сортировки слов, тогда имеет смысл, что порядок словаря поддерживается. В противном случае логика сортировки была бы бессмысленной. Я с тобой. Я не верю, что словарь может переупорядочивать его элементы произвольно. – JNevill

ответ

2

Никто не может дать пример Scripting.Dictionary объекта возвращения ключей/элементов в другом порядке, чем они были добавлены, потому что Scripting.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 

Вы могли бы иметь в виду стенограмме «перезапись» метод добавления ключей без проверки, чтобы увидеть его они существуют. Если вы попытаетесь установить .Add, то появится ключ, который существует ошибка 457. Однако, если вы просто напишите Keys и Items в словарь, новый ключ и элемент будут созданы, если ключ не существует, но если ключ существует, ключ остается тем же, и элемент перезаписывается.

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 

по перезаписыванию метод немного быстрее, чем проверка, если ключ .Exists но поведение следует понимать. Я использовал перезапись для намеренного получения последнего элемента для любого ключа в списке с дубликатными ключами, но это был особый случай. Обратите внимание, что .Key не находится в оригинальном исполнении; он просто заменил его .Item на более поздний.

Если вы добавили справочную библиотеку Runtime Microsoft Scripting, вы можете использовать Early Binding в объявлении переменной. Это позволяет создавать несколько более быстрый словарьный объект и выставлять другие методы индексированного перечисления.

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, я нашел это индексированное перечисление ненадежно, когда словарь .Count превышает целое число (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 
+0

Спасибо за вашу информацию. Мне любопытно, что вы имеете в виду под «индексированным перечислением, ненадежным, когда словарь .Count превышает целое число со знаком (32,767)»? – JohnM

+0

Я собирал переписку словарной документации и обнаружил «ненадежные результаты» с большим количеством клавиш словаря. Пока я не завершу тестирование в более широком числе условий, я не могу точно определить проблему, поэтому использовал термин «ненадежный». – Jeeped

+0

Можете ли вы предоставить любой случай, который вы обнаружили ненадежным? – JohnM

Смежные вопросы