Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Словарь (Scripting.Dictionary). Соответствие массивов ключей и элементов между собой
 
Доброго времени суток, Планетяне!

Пару раз видел тут на планете, как мэтры предупреждали (Hugo, Михаил Витальевич), что при цикле по массивам, полученным из ключей и элементов словаря, их соответствие не обеспечивается — то есть i-ый элемент массива может быть НЕ РАВЕН i-ому ключу:
Тест
Вопросы: есть ли этому подтверждения, сталкивался ли кто-то с этим, как поймать такой баг и где прочитать о не обеспечении соответствия?

Словари и так шустрые, но получение 2ух массивов (ключей и элементов) из словаря иногда бывает намного удобнее цикла по элементам и хочется уверенно использовать этот способ  :)

!!! ВАЖНО !!!
Обсуждается подтверждение несоответствия при раннем связывании, т.к. при позднем сюрпризы привычны (я его не использую)
Изменено: Jack Famous - 31 дек 2020 10:21:15
Реквизиты для благодарности и контакты для связи — в профиле
 
Приветствую.
словари юзаю довольно долго, но ни разу не наступал этот страховой случай.
 
doober, благодарю за обратную связь — от спеца с вашим опытом это многое значит  ;)
Изменено: Jack Famous - 30 дек 2020 17:07:51
Реквизиты для благодарности и контакты для связи — в профиле
 
Моя тоже сие токмо на форуме читала.
 
Добавил ссылку на Hugo о не гарантии
Sanja в той теме говорит, что тоже в курсе, хоть и ни разу не сталкивался  :D
Изменено: Jack Famous - 30 дек 2020 18:02:07
Реквизиты для благодарности и контакты для связи — в профиле
 
Еще где-то Михаил Батькович С сие упоминал. (Как мне помнится)
 
RAN,  ;)
Добавил замечание от Михаила Витальевича и ищу спецификацию
Изменено: Jack Famous - 30 дек 2020 17:56:07
Реквизиты для благодарности и контакты для связи — в профиле
 
Да, я сиё тоже упоминал; сам я это взял, емнип, у Hugo, более того, один раз, года четыре назад сам на это нарвался, причем словарь был не большой - чуть более ста элементов.
С тех пор пару keys - items я не использую; прохожу по ключам, значения беру из словаря по ключу - это чуть дольше но надежно.
А то что ни разу не нарывался... так а как ты ошибку заметишь, если специально внимательно не проверять?
Изменено: Михаил Витальевич С. - 30 дек 2020 18:38:15
 
Такая ошибка может возникнуть(уж точно чаще), если используется позднее связывание. Равно как может появится фокус с неочисткой ключей методом RemoveAll. При раннем связывании проблем быть не должно. Но это не точно  :D  При раннем такой бяки не встречал.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Дмитрий(The_Prist) Щербаков написал:
если используется позднее связывание
я раннее связывание ни разу не использовал...
 
Я про это кажется читал в какой-то статье. Правда позже хотел найти этот источник, но не нашёл.
 
Цитата
Hugo написал:
Я про это кажется читал в какой-то статье.
вот так и рождаются мифы.  :D

Жена приходит домой и говорит:
- Ой, у нас на работе бабы говорят, что тебя скоро повысят по службе.
- С чего бы это, у меня никаких заслуг нет.
Немного погодя его действительно повысили по службе. Через некоторое
время жена приходит и говорит:
- Ой, у нас на работе бабы говорят, что у тебя какие-то нелады с
документами, что будет ревизия, и тебя посадят.
Мужик удивляется:
- С чего они это взяли, твои бабы? Все у меня в порядке.
Действительно, вскоре была ревизия, и мужика посадили. Взволнованная
жена прибегает к нему на свидание:
- Ой, была у адвоката, такого хорошего защитника тебе нашла...
- Хрен с ним, с адвокатом. ты скажи, что бабы-то на работе говорят?
По вопросам из тем форума, личку не читаю.
 
Цитата
Михаил Витальевич С.: я раннее связывание ни разу не использовал
а я позднее уже год как не использую в своих проектах. Раннее быстрее и удобнее - не вижу смысла отказываться)))

Дмитрий(The_Prist) Щербаков, спасибо  ;)

Цитата
Hugo: позже хотел найти этот источник, но не нашёл
хотелось бы почитать всё-таки  :D
Изменено: Jack Famous - 30 дек 2020 21:25:28
Реквизиты для благодарности и контакты для связи — в профиле
 
Цитата
Дмитрий(The_Prist) Щербаков написал:
с неочисткой ключей методом RemoveAll.
с этим сталкивался, при многократном запуске макроса сразу после
Set d= CreateObject("Scripting.Dictionary")
d.count кажет 1
или
d.count пишет 0, а d.exists(...) пишет уже есть
не говорю, что всегда, но на нескольких проектах это повторялось постоянно
Изменено: Ігор Гончаренко - 31 дек 2020 00:24:44
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Ігор Гончаренко: с этим сталкивался
до использования раннего связывания, я часто с этим (неочистка словаря методом .RemoveAll при позднем связывании) сталкивался и это довольно легко выловить. Данная проблема не относится к вопросу
Изменено: Jack Famous - 31 дек 2020 08:03:06
Реквизиты для благодарности и контакты для связи — в профиле
 
Алексей, я не понял в чем вопрос? В том, что в словаре не обеспечивается и неопределен порядок следования элементов? Да это так.
Объект Dictionary является эквивалентом ассоциативного массива языка PERL.
Ассоциативные массивы в Perl являются реализацией хэш-таблиц.
В отличие от обыкновенных массивов, у ассоциативных массивов порядок следования элементов не определен и к ним нельзя обратиться по числовому индексу.
Хеш таблицу нельзя сравнивать с массивом, в т.ч. и по порядку следования элементов.
Матчасть:
https://docs.microsoft.com/ru-ru/office/vba/language/reference/user-interface-help/dictionary-object#remarks

http://www.codenet.ru/webmast/perl/hash.php

Или я тебя не так понял?
А вот по поводу работы методов при раннем связывании и не работы при позднем это интересно, так не должно быть. Есть примеры?
Изменено: bedvit - 31 дек 2020 09:42:52
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, приветствую, Виталий! Вопрос не про порядок (хотя я не замечал, чтобы он отличался от порядка наполнения), а про соответствие ключа и значения по индексам при выгрузке "коллекций" .Keys и .Items в отдельные массивы. Странно, что ты спрашиваешь, ведь я даже тест прикрепил…

Цитата
bedvit: по поводу работы методов при раннем связывании и не работы при позднем
Попробовал сделать файл без библы с таким кодом, но ничего
в отличие от несоответствия, которого я не встречал, НЕочистка методом .RemoveAll мне встречалась не раз (на позднем)

UPD по ссылке на codenet:
«В отличие от обыкновенных массивов, у ассоциативных массивов порядок следования элементов не определен и к ним нельзя обратиться по числовому индексу»к элементам массива спокойно можно обращаться по ключу (.Items(i) или .Items()(i) — для позднего) + порядок такой же, как при наполнении (во всяком случае, не замечал иного)
Пруф (скрин+файл)


«При вызове keys возвращается список ключей ассоциативного массива. При вызове values возвращается список значений ассоциативного массива. Эти функции возвращают списки в одинаковом порядке, хотя он и не имеет ничего общего с порядком добавления элементов в массив»
Ну вот тут как раз написано, что соответствие есть, но надо учитывать, что тут не о словарях…
Изменено: Jack Famous - 31 дек 2020 10:46:10
Реквизиты для благодарности и контакты для связи — в профиле
 
Добрый день.
Никогда не сталкивался ни с одной из перечисленных в теме проблем Scripting.Dictionary, как и упоминаний о них на зарубежных Excrl/VBA-форумах.
Полагаю, что какие-то проблемы могли быть вызваны иными причинами кода, не связанными непосредствено со Scripting.Dictionary.
Если кому-то вдруг попадется пример с воспроизведением проблем, выложите, пожалуйста, с удовольсвием бы проанализировал.
 
ZVI, приветствую!
Я вряд ли поймаю, т.к. использую ранее связывание, а вообще НЕочистка через .RemoveAll на позднем встречается настолько часто (при этом сходу воспроизвести в простом коде не вышло), что её заменяют (в решениях на форуме) на Set dic = Nothing уже чуть ли не автоматически
Изменено: Jack Famous - 11 янв 2021 09:32:05
Реквизиты для благодарности и контакты для связи — в профиле
 
Добрый вечер, Алексей.
Запутаться можно и с ранним связыванием, вот, например: не запуская кода, показанного ниже, что ожидать в 3-х сообшениях?
Код
Sub Test()
'Требуется VBE-Tools-References-Microsoft Scripting Runtime 
  
  Dim dic As New Dictionary
  
  dic.Add "Key", "Item"

  MsgBox dic.Count()

  Set dic = Nothing
  
  If dic Is Nothing Then
    MsgBox "dic is nothing"
  Else
    MsgBox "dic is not nothing"
  End If
  
  MsgBox dic.Count()
  
End Sub

Здесь все работает правильно, но, не понимая некторых внутренних правил, можно ошибиться в причинах поведения.
Сравнивать dic.RemoveAll c Set dic = Nothing не очень-то корректно, т.к. это разные методы с разным результатом  
RemoveAll  только удаляет элементы , но оставляет объект живым, а  Set to Nothing принудительно анигилирует и сам объект.
С поздним связыванием Set dic = Nothing в конце кода рекомендуется для устранения утечек памяти, которые иногда могут проявиться.
Полагаю, что с претензиями к  объектам Scripting.Dictionary тоже что-то не учли в коде, т.к. с их непредсказуемостью я ни разу не  сталкивался. Хорошо бы, конечно, ссылку на конкретный пример с проблемой, если вдруг попадется - сообщите, пожалуйста.
Изменено: ZVI - 11 янв 2021 21:51:48
 
Цитата
ZVI: что ожидать
думал: 1; not nothing; Null — ошибся только с Null - там просто 0 будет
Цитата
ZVI: Сравнивать dic.RemoveAll c Set dic = Nothing не очень-то корректно
ни в коем случае — ОБНУЛЕНИЕ объекта использовалось ВМЕСТО его ОЧИСТКИ по причине того, что она не всегда срабатывала при позднем связывании
Цитата
ZVI: Set dic = Nothing в конце кода рекомендуется для устранения утечек памяти
читал о таком, но пока не сталкивался и не использовал — спасибо
Цитата
ZVI: конкретный пример с проблемой,
если поймаю, то обязательно сюда выложу  ;)

P.S.: я правильно понимаю, что можно из словаря спокойно получать 2 массива (ключи и значения) и не беспокоится о их соответствии?…
Изменено: Jack Famous - 12 янв 2021 09:18:25
Реквизиты для благодарности и контакты для связи — в профиле
 
Цитата
Jack Famous написал: ...можно из словаря спокойно получать 2 массива (ключи и значения) и не беспокоится о их соответствии?
Да. Но ждем примеров, когда  это (якобы) не работает.
 
На всякий случай - если в коде #20 вместо Dim dic As New Dictionary написать:
Код
  Dim dic As Dictionary
  Set dic = New Dictionary

или
Код
  Dim dic As Object
  Set dic = CreateObject("Scripting.Dictionary")

то код поведет себя иначе
Изменено: ZVI - 12 янв 2021 11:32:02
 
Цитата
ZVI: код поведет себя иначе
это важно - спасибо  :idea:
Про позднее, понятно, а вот раннее с другим подключением я даже не подумал бы  :D
В массиве по-другому
Изменено: Jack Famous - 12 янв 2021 12:51:54
Реквизиты для благодарности и контакты для связи — в профиле
 
Алексей, у  Вас код другой, в нем так и должно быть.
Вот пример с массивом по теме сообщения #20:
Код
'Требуется VBE-Tools-References-Microsoft Scripting Runtime
Sub Test1()

  Dim i As Long
  Dim a(0 To 2) As New Dictionary

  For i = 0 To UBound(a)
    Set a(i) = Nothing
    Debug.Print i, a(i) Is Nothing
  Next

End Sub

' Для сравнения
Sub Test2()

  Dim i As Long
  Dim a(0 To 2) As Dictionary

  For i = 0 To UBound(a)
    Set a(i) = New Dictionary
  Next

  For i = 0 To UBound(a)
    Set a(i) = Nothing
    Debug.Print i, a(i) Is Nothing
  Next

End Sub
Изменено: ZVI - 12 янв 2021 21:20:47
 
Цитата
ZVI: у  Вас код другой
у меня обычный массив со словарями внутри, а у вас словарные массивы одноэтапного или двухэтапного присвоения — так что это просто ещё вариант  :D
За тесты спасибо  :)
Изменено: Jack Famous - 13 янв 2021 08:55:38
Реквизиты для благодарности и контакты для связи — в профиле
Страницы: 1
Читают тему (гостей: 1)
Наверх