Страницы: 1 2 След.
RSS
Сравнительная характеристика массивов, коллекций и словарей
 
Здравствуйте.

Расскажите или укажите, есть ли где сравнительное сопоставление трех понятий: массив, коллекция, словарь.
Хочу понять, когда и зачем их лучше использовать, в чем общее, в чем различие.
Изменено: borro - 26.01.2017 02:14:53
желаю всем счастья
 
Общее: по сути это все массивы.
Различия: дофига. У коллекций свой набор методов, у словарей свой. У массивов в чистом виде по большому счету нет ничего. Но применимо к VBA чисто массив - arr() - можно заполнить очень быстро без цикла значением диапазона ячеек или формулами. Словари и коллекции требуют обязательного цикла для добавления элементов.
Преимущество коллекций(New Collection) - могут использоваться и в Windows и в MAC. А словари - только в Windows. Так же при добавлении элемента в коллекцию можно указать куда поместить новый элемент: до или после. Это дает возможность делать быструю сортировку уникальных значений.
Преимущество словарей: есть проверка наличия ключа встроенным свойством(Exists), что позволяет работать с ними быстрее. Так же можно настроить методы сравнения текста через свойство CompareMode. Если установить как 1 - то регистр не будет учитываться методом Exists при сравнении имеющихся в словаре элементов.

Но однозначно сказать что лучше, а что хуже нельзя. Все зависит от ситуации.

P.S. Не забывайте отписывать в своих темах, в которых получили ответы:
http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=86715&TITLE_SEO=86715-kak-pol...
http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=87222&TITLE_SEO=87222-ne-udae...

Иначе есть шанс потом ответы не получить...
Изменено: The_Prist - 25.01.2017 17:22:26
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Спасибо.
желаю всем счастья
 
Например, в некотором цикле будут собираться данные вида:
Артикул1 Наименование1 число1 число2 ... число15
Артикул1 Наименование1 другоечисло1 другоечисло2 ... другоечисло15
Артикул2 Наименование1 число1 число2 ... число15
Артикул2 Наименование2 число1 число2 ... число15
...

Используя язык баз данных, пара значений "Артикул" и "Наименование" являются ключом для каждой строки массива данных.
На каждой итерации получения строки данных надо в некий тип данных(массив, коллекция, словарь) вносить получаемые значения таким образом:
1. если в хранилище нет пары с ключом артикул+наименование, то надо в него вносить получаемую строку
2. если уникальная пара уже есть в хранилище, то надо к хранящимся числовым значениям прибавить числовые значения новой строки, используя данные об артикуле и наименовании

Вопрос - в данной задаче надо использовать какой из типов данных?
желаю всем счастья
 
Посмотрите в топике Dictionary - это совсем не сложно!
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
ОГРОМНЫМ плюсом словарей является наличие в них методов Items и Keys возвращающих "одним махом" массивы ЗНАЧЕНИЙ и КЛЮЧЕЙ словаря
Да и вообще, у коллекций всего 1 свойство (.Count) и 4 метода (.Add .Item .Remove .Clear), а у словарей 4 свойства (.CompareMode .Count  .Item .Key) и 6 методов (.Add .Exists .Items .Keys .Remove .RemoveAll), что придаёт работе с ними значительно большую гибкость.
По приведённой выше ссылке я выкладывал файл-шпаргалку со свойствами, методами и примерами работы со словарями.
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Цитата
borro написал:
Артикул1 Наименование1 число1 число2 ... число15
Артикул1 Наименование1 другоечисло1 другоечисло2 ... другоечисло15
Артикул2 Наименование1 число1 число2 ... число15
Артикул2 Наименование2 число1 число2 ... число15
Так что уникальное? Похоже, что Артикул?
Ну и используйте их как ключи к значениям (записям) словаря. А в каждой записи могут лежать как массивы, так и подчинённые словари.
Там по ссылке есть пример использования словаря словарей.
Добавление ключа с пустой записью происходит автоматически при попытке обращения к словарю по отсутствующему ключу.
Единственный минус словарей по сравнению с коллекциями - это отсутствие у метода .Add опциональных параметров [Before | After], которые позволяют достаточно просто производить сортировку записей внутри коллекции.
Но это нужно, имхо, достаточно редко.
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Цитата
Alex_ST написал: Так что уникальное? Похоже, что Артикул?
Совсем не похоже.
Цитата
borro написал: Используя язык баз данных, пара значений "Артикул" и "Наименование" являются ключом для каждой строки массива данных
Уникальна ПАРА (Артикул и Наименование), поэтому в данном случае лучше использовать составной ключ (Артикул&Наименование)
Согласие есть продукт при полном непротивлении сторон
 
Доброе время суток.
Со словарями есть один не приятный момент, столкнулся случайно. Если выполнить
Код
Dictionary.RemoveAll
Set Dictionary = Nothing
, то это не приводит к автоматическому освобождению объектов-значений словаря. Они как-бы существуют вплодь до принудительного End, даже не до завершения метода, в котором создавался словарь. С коллекциями такого не происходит.
 
Как-то я никогда особо освобождением памяти не заморачивался, хотя словари люблю и использую часто...
Обычно использую не явное позднее связывание типа
Код
With CreateObject("Scripting.Dictionary"): .CompareMode = vbTextCompare   ' создаем временный словарь
…
End With

Никогда никаких проблем не возникало. Может быть, при таком связывании их просто нет?
Или просто задачи не настолько тяжёлые, чтобы память ощутимо отожрать?
Изменено: Alex_ST - 26.01.2017 16:48:01
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Алексей, дело не в памяти - её хватало. А вот блокировка объектов не снималась. Пришлось делать вариант на Collection. Столкнулся не в Excel - в VBA IBM Rational System Architect.
Изменено: Андрей VG - 26.01.2017 16:52:58
 
Цитата
borro написал:
Вопрос - в данной задаче надо использовать какой из типов данных?
- словарь для ключей с индексами, и массив для данных. Массив можно использовать тот же исходный.
 
Цитата
Андрей VG написал:
то это не приводит к автоматическому освобождению объектов-значений словаря
Интересно, а как это узнали?
There is no knowledge that is not power
 
Цитата
Андрей VG написал: А вот блокировка объектов не снималась
Я вот тоже буквально сегодня заметил нечто подобное. Если для словаря используется раннее связывание словарь объявляется переменной (Dim dic1: Set dic1 = CreateObject("Scripting.Dictionary")), то наблюдаются какие-то глюки при попытке добавить НЕ уникальный ключ. С конструкцией With CreateObject("Scripting.Dictionary") такого не происходит
Изменено: Sanja - 26.01.2017 22:12:25
Согласие есть продукт при полном непротивлении сторон
 
Цитата
Sanja написал:
используется раннее связывание (Dim dic1: Set dic1 = CreateObject("Scripting.Dictionary")
Сёма, это-таки позднее связывание :) Раннее будет так:
Код
Dim dic1: Set dic1 = New Scripting.Dictionary
А при случае использования With очищение памяти от объектов происходит более корректно, когда-то мы вроде это обсуждали уже. Это касается не только словарей, кстати.  
Изменено: The_Prist - 26.01.2017 21:51:49
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Ага, Семёёён Семёёёныч  :). Но факт наблюдался
Согласие есть продукт при полном непротивлении сторон
 
Цитата
The_Prist написал: Не забывайте отписывать в своих темах...
Похоже, что Дмитрий у нас провидец...
borro заварил кашу и исчез. А мы тут его о чём-то спрашиваем, что-то советуем, дискуссию о высоких материях ведём...
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Цитата
SuperCat написал: Интересно, а как это узнали?
Да есть в этом RSA возможность делать перекрёстную связь между объектами. Пользователь добавляет ссылку с родительского объекта на дочерний и у дочернего появляется в свойствах ссылка на родительский. Соответственно, в VBA нужно ссылки добавлять только с одной стороны, иначе, так как объекты (родительский и дочерний) при их создании открыты на редактирование, то невозможно сохранить не тот не другой. При загрузке же данных описание связей идёт как попало. Вот я и сделал поиск родительского объекта для дочерних через словарь. Сохранил родительские, очистил словарь. Стал сохранять дочерние с установленными ссылками на родительские, а RSA выбрасывает объект заблокирован. Переделал на коллекции - ушло.
 
Доброго утра. Спасибо, Sanja за совет.
Дело в том, что остальные обсуждения моего последнего вопроса не касались, поэтому я молчал. Да и что отвечать, тут только впитывать информацию. Простите, если что не так :)
Изменено: borro - 28.01.2017 10:14:27
желаю всем счастья
 
Цитата
borro написал:
Дело в том, что остальные обсуждения моего последнего вопроса не касались
А вопрос был какой последний?
Цитата
borro написал:
Вопрос - в данной задаче надо использовать какой из типов данных?
Вы все же получили после этого ответ от Alex_ST - словари.
Цитата
Alex_ST написал:
Посмотрите в топике  Dictionary - это совсем не сложно!
Но отписаться понятно-непонятно, оно-не оно уже не посчитали нужным. А между тем это проявление элементарной вежливости и уважения к отвечающим - отписаться ответившему: помогло - не помогло, понятно - не понятно и т.п. Чтобы все понимали имеет ли смысл дальше что-то предлагать или обсуждать. Т.к. Вы этого не делаете - тема развивается своим ходом, а Вас берут на заметку - типа это тот человек, который темы создает, ответы получает и сваливает. В результате что будет? Правильно. Вам просто перестанут отвечать, ибо потребительское отношение не нравится никому...
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Есть одна тонкость с
Цитата
Alex_ST написал:
ОГРОМНЫМ плюсом словарей является наличие в них методов Items и Keys возвращающих "одним махом" массивы ЗНАЧЕНИЙ и КЛЮЧЕЙ словаря
- Microsoft не обещает точное соответствие этих двух массивов, т.е. вываливать их рядом небезопасно.
В ответственных задачах нужно к каждому ключу получать значение в индивидуальном порядке. Да и transpose на больших объёмах может сглючить...
Изменено: Hugo - 28.01.2017 12:01:49 (буковка потерялась...)
 
Согласен с Игорем. Лучше создавать под это отдельный массив и в цикле выгружать туда сначала ключ, а потом соответствующий ключу элемент.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Не совсем по теме, но близко ))
Недавно столкнулся с тем, что перебор коллекции циклом работает очень медленно: раньше приходилось обрабаывать относительно небольшие по размеру коллекции, а тут попалась довольно большая. Так вот: уже после 1000-го элемента коллекции увидел, что процесс "не летает" )) А нужно было перебрать порядка 30 000 элементов. ZVI подсказал, что не следует перебирать коллекции по индексу (For i = 1 to Коллекция.Count) - скорость нелинейно падает. Для перебора коллекции следует использовать цикл For Each - Next. Переделал - перемена поразительна!
Лично я этого не знал - может кому ещё пригодится )
 
Юрий М, очень пригодилось, спасибо!
Единственно от себя дабавлю - это также справедливо и для словарей. Вложенный цикл по двум словарям (для каждого элемента первого перебирались все элементы второго, 3000 и 1500 элементов соответственно) - for j=0 to count просто "умер", после замены на for each - даже не заметно на фоне остальных операций
 
Цитата
Юрий М написал:
Лично я этого не знал - может кому ещё пригодится )
Что-то я этот совет Юрия либо пропустил, либо просто забыл...
Сейчас практически не программирую. Но несколько лет назад всё равно почему-то предпочитал в своих разработках применять циклы For Each - Next. Наверное, интуитивно  :)
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Цитата
Alex_ST: почему-то предпочитал в своих разработках применять циклы For Each - Next
они надёжнее, позволяют собирать новый или изменять текущий массив по имеющемуся в цикле индексу. Например, цикл по тысячам областей (фильтр столбца по видимым) нельзя делать через For Each, потому что будет ошибка.

Честно говоря, есть сомнения по поводу скорости перебора словаря (коллекции не использую). Может, при позднем подключении, если только (я раннее использую). Тестов не вижу))
Изменено: Jack Famous - 01.07.2022 17:12:13
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Действительно, перебор по индексам "в лоб" - не для словарей.
Не понимаю, зачем это может быть нужно, но, если всё-таки нужно, то взять массивы из словаря и перебирать их будет многократно (на примере — в 8 раз для 100 тыс ключей) быстрее
Файл и Код
При раннем связывании, разница в соответствии "ключ-значение" в массивах при их получении из словаря, не замечена. При позднем - я не уверен.
При этом ПОРЯДОК РАСПОЛОЖЕНИЯ ПАР элементов в словаре, вполне может не соответствовать их ПОРЯДКУ при НАПОЛНЕНИИ словаря
Что я имею в виду

Ссылки по теме:
bedvit про порядок ключей-значений
Словарь (Scripting.Dictionary). Соответствие массивов ключей и элементов между собой
Получить значение по ключу. Массив, Словарь и Коллекция, Get Item by Key. Array vs Dictionary vs Collection
Изменено: Jack Famous - 04.07.2022 09:37:34
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал: 'dic.Keys(i) вообще не факт что равен arr(i)
Добрый день, Алексей.
Вы же сами в коде создали ключи словаря, начиная с нулевого, а не с первого, как в значении начального элемента массива.
В массиве точно так же значения массива, не совпадают с индексом массива: arr(0) <> 0
Это ошибка в представлении о логике кода, а не проблема словаря.
Код должен быть, например таким:
Код
Sub t()
  Dim dic As New Dictionary
  Dim arr(), i&
  arr = Array(0, 1, 2, 3, 4)
  For i = LBound(arr) To UBound(arr)
    dic(i) = "Item " & i
    Debug.Print dic.Keys(i) = arr(i), dic.Keys(i), arr(i)
  Next
End Sub
' Или таким
Sub t1()
  Dim dic As New Dictionary
  Dim arr(), i&
  arr = Array(1, 2, 3, 4, 5)
  For i = LBound(arr) To UBound(arr)
    dic(arr(i)) = "Item " & i
    Debug.Print dic.Keys(i) = arr(i), dic.Keys(i), arr(i)
  Next
End Sub

Цитата
Jack Famous написал: При этом ПОРЯДОК РАСПОЛОЖЕНИЯ ПАР элементов в словаре, вполне может не соответствовать их ПОРЯДКУ при НАПОЛНЕНИИ словаря
Это утверждение некорректное, так как касается внутреннего механизма работы словаря, а не его документированного внешнего интерфейса (свойств и методов .Item, .Keys, .Values и др.)
Словари всегда обеспечивают соответствие в массивах .Keys и .Values порядку заполнения словаря.
В словаре всегда доступ по ключу соответствует доступу по индексу.
Об этом мы в теме по Вашей 2-й ссылке уже общались - здесь.
Изменено: ZVI - 02.07.2022 15:40:30
 
ZVI, приветствую! Всегда рад видеть вас в своих (и не только) темах  :idea:

Цитата
ZVI: Вы же сами в коде создали ключи словаря, начиная с нулевого, а не с первого, как в значении начального элемента массива
спасибо, согласен, оплошал, поправил  :)

Цитата
ZVI: Словари всегда обеспечивают соответствие в массивах .Keys и .Values порядку заполнения словаря … уже общались
там были только тесты, а хотелось бы увидеть документальное подтверждение, ведь никакими тестами нельзя доказать правило, а можно только приближаться к нему. А вот когда в докУменте будет написано — другое дело. Во всяком случае, логика Виталия мне понятна: они сказали, что это аналог перловых таблиц, у перловых таблиц порядок сбора и хранения не соответствует, а значит и у словарей тоже.
Тестами пытался повторить, но не вышло - пока что всегда соответствует  :D
Изменено: Jack Famous - 04.07.2022 09:38:07
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Добрый вечер, Алексей.
Гипотеза - это предположение для объяснения каких-то явлений. Но явлений-то в данном случае и нет.
Слова Виталия, в принципе, могут касаться только внутреннего устройства словаря, а не его внешнего интерфейса (см. моё сообщение выше).
Но т.к. и Вы, и Виталий на форуме - авторитеты, то подобное утверждение про словари запросто может кого-то ввести в заблуждение. Чего не хотелось бы. Собственно, поэтому и подключаюсь в тему.
Страницы: 1 2 След.
Наверх