Страницы: 1
RSS
Тесты. Массивы. Операции, методы и способы работы с ними
 
Доброго времени суток, Планетяне!

Этой темой открываю для себя новую рубрику тем — Тесты.
Предлагаю делиться фишками и плюшками для ускорения/удобства/понятности работы в VBA Excel  ;)

Вот мой первый список тестов. Многое для меня было неожиданно и удивительно. Отдельно отмечу, что GoTo-переходы очень даже полезны бывают ;)
КОД
Ссылка на тестовый стенд (файл 6,6 Мб из-за списков на листах)

UPD 27.09:
1. Добавлен макрос «ПустыеВыделить»
В частности, формирование диапазона из строки адресов через запятую, если она длиннее 255 символов — по этой теме.

2. Добавлен макрос «СтрокаСкоростная»
В нём подчёркнуто превосходство Redim Preserve одномерного массива над элементами словаря для создания текстовой строки по условию.

3. Добавлен макрос «МассивМассивов»
Я научился создавать массив массивов  :D — бывает очень удобно. В частности, если при одном цикле, нужно записывать, N видов информации, то для этого как нельзя лучше подходит функция, возвращающая массив, состоящий из N одномерных массивов. Это очень универсально тем, что любой из полученных массивов можно очень быстро преобразовать (Join) в текстовую строку и использовать её в качестве списка сравнения, используя супербыстрый метод без циклов.
Прослеживается линейная зависимость. Создание массива, состоящего из 2 одномерных массивов, одинаковых по количеству элементов, занимает примерно в 2 раза больше времени, нежели создание одного из них (вроде очевидно, но всё же). Ну и да - словари тут опять капитально проигрывают, так что пока вижу смысл их использовать только для создания уникальных списков или там, где необходимо проверять по .Exist (что тоже надо тестить - я уже загорелся  :D ).

4. Макрос «Перебор» заменён на «ПереборСтрокиСтолбцы»
Действительно наблюдается совсем незначительное, но всё-таки стабильное (да и предсказуемое) преимущество при переборе стандартной вертикальной структуры от столбцов к строкам.
Изменено: Jack Famous - 16.10.2018 10:20:49
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
ОБНОВЛЕНО
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Привет, Алексей
Цитата
'Неожиданная сокрушительная победа Redim Presrve над Словарём в случае, если из массива нужно собрать новый массив по условию
Почитайте  Автор: Стивенс, Род Название: Visual Basic. Готовые алгоритмы, чтобы понять почему ;)
Цитата
'Где-то слышал о приемуществах StrComp. Не в этом примере…
Попробуйте сравнить с UCase$(x) = UCase$(temp) и StrComp(x, temp, vbTextCompare) = 0
Общее замечание сравнивать 95мск и 100мск фактически бессмысленно. Попробуйте один и тот же код прогнать несколькими запусками, включая после нескольких перезагрузок Excel и системы (естественно, дав отстояться) и найти стандартное отклонение.
 
Цитата
Андрей VG написал:
Попробуйте сравнить с UCase$(x) = UCase$(temp) и StrComp(x, temp, vbTextCompare) = 0
интересно, в какую сторону будет преимущество
 
Здравствуйте, коллеги! Думаю, что Андрей задал "хитрый" вопрос и победитель единоборства будет меняться в зависимости от конфигурации (версии Excel).
Владимир
 
Цитата
Андрей VG написал:
Почитайте  Автор: Стивенс, Род Название: Visual Basic. Готовые алгоритмы, чтобы понять почему  
Андрей, привет! Заинтриговал :)
Jack Famous, когда-то делал сравнение словаря и коллекции, а так же до кучи Scripting.FileSystemObject и Dir (искал наиболее производительный алгоритм поиск файлов по маске, имени)
Код
Sub Test_Collection_vs_Dictionary() ' - что быстрее словарь или коллекция
Dim t, y As String, arr(100000, 1) As String, i As Long, x As Long, xEnd As Long, FileTemp As String
Dim Coll As Collection: Set Coll = New Collection
Dim Dict: Set Dict = CreateObject("Scripting.Dictionary")
Dim FSO: Set FSO = CreateObject("Scripting.FileSystemObject")

xEnd = 100000 'количество итераций

For x = 1 To xEnd 'МАССИВ для проверки
arr(x, 0) = x
arr(x, 1) = "\\0.0.0.0\work$\05_КД\05-04_КС\КАТАЛОГИ\тест\0009613%01-С8-01.jpg" & x
Next

t = Timer
For x = 1 To xEnd 'добавляем элементы
Coll.Add arr(x, 0), arr(x, 1)
Next
Debug.Print "Внесение данных, Collection.Add = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем существующие элементы
y = Coll.Item(arr(x, 1))
Next
Debug.Print "Поиск верных данных, Collection.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем не существующие элементы
On Error Resume Next
Err = 0
y = Coll.Item("\\0.0.0.0\work$\05_КД\05-04_КС\КАТАЛОГИ\тест\0009613%01-С8-01.jpg")
If Err Then y = 0: On Error GoTo 0
Next
Debug.Print "Поиск не верных данных, Collection.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'добавляем элементы
Dict.Add arr(x, 1), arr(x, 0)
Next
Debug.Print "Внесение данных, Dictionary.Add = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем существующие элементы
y = Dict.Item(arr(x, 1))
Next
Debug.Print "Поиск верных данных, Dictionary.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем не существующие элементы
y = Dict.Item("\\0.0.0.0\work$\05_КД\05-04_КС\КАТАЛОГИ\тест\0009613%01-С8-01.jpg")
Next
Debug.Print "Поиск не верных данных, Dictionary.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'проверяем есть ли ключ
y = Dict.Exists(arr(x, 1))
Next
Debug.Print "Проверяем есть ли ключ, Dictionary.Exists = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем существующие элементы
y = Coll.Item(arr(50000, 1))
Next
Debug.Print "Поиск одного и того же верного значения, Collection.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем существующие элементы
y = Dict.Item(arr(50000, 1))
Next
Debug.Print "Поиск одного и того же верного значения,  Dictionary.Item = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем существующие элементы
y = Dict.Exists(arr(50000, 1))
Next
Debug.Print "Проверяем есть ли ключ - одинаковый для всех итераций,  Dictionary.Exists = " & Timer - t

t = Timer
For x = 1 To xEnd 'ищем в массиве
    For i = 1 To xEnd
        If arr(i, 1) = arr(35, 1) Then y = arr(35, 0): Exit For
    Next
Next
Debug.Print "Поиск одного и того же верного значения МАССИВ (35й элемент) = " & Timer - t

FileTemp = "C:\Windows\system.ini"
t = Timer
For x = 1 To xEnd 'ищем файл
    y = FSO.FileExists(FileTemp)
Next
Set FSO = Nothing
Debug.Print "Поиск одного и того же верного значения, FSO.FileExists = " & Timer - t

FileTemp = "C:\Windows\system.ini"
t = Timer
For x = 1 To xEnd 'ищем файл
    y = Dir(FileTemp) <> ""
Next
Debug.Print "Поиск одного и того же верного значения, Dir = " & Timer - t

End Sub

Итого, время в секундах на 100 000 итераций  - добавление, поиск текста примерно 70 символов:
Внесение данных, Collection.Add = 1,06543
Поиск верных данных, Collection.Item = 0,3808594
Поиск не верных данных, Collection.Item = 0,4990234
Внесение данных, Dictionary.Add = 0,6176758
Поиск верных данных, Dictionary.Item = 0,5703125
Поиск не верных данных, Dictionary.Item = 0,07910156
Проверяем есть ли ключ, Dictionary.Exists = 0,6557617
Поиск одного и того же верного значения, Collection.Item = 0,4052734
Поиск одного и того же верного значения,  Dictionary.Item = 0,3447266
Проверяем есть ли ключ - одинаковый для всех итераций,  Dictionary.Exists = 0,4121094
Поиск одного и того же верного значения МАССИВ (35й элемент) = 0,3149414
Поиск одного и того же верного значения, FSO.FileExists = 5,554199
Поиск одного и того же верного значения, Dir = 7,03125

По массивам - при поиске со средним значением не более 35 элемента в массиве - поиск по массиву быстрее коллекции и словаря. т.е. при равномерной вероятности найти результат - это массив из 70-75 элементов (0-70).
Потом проигрывает.
Возможно при других условиях (неравномерного поиска или при проверке существует ли ключ Dictionary.Exists) можно дойти и до 100 элементов, здесь многое зависит от структуры данных)
Изменено: bedvit - 23.09.2018 09:08:11
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
Заинтриговал
Привет, Виталий.
Да там по этой теме у Алексея всё проще. Он последовательно записывает в массив удовлетворяющие шаблону значения, а потом после завершения всех циклов - изменяет размер массива по числу этих значений.
Со словарём пытается сделать тоже самое. Естественно, запись/чтение в массиве всегда быстрее чем в словаре или коллекции. А книжку упомянул, потому что там хорошо описан код для АВЛ-деревьев - собственно словаря и для хэш-таблиц - коллекции. Уже по объёму кода, обслуживающего чтение/запись, видно, что словарь и коллекция при использовании их в качестве массива последовательно нумерованных элементов (ключей) всегда медленнее массива на алгоритмах доступа к элементу по его номеру.
 
Доброго времени суток, Планетяне!
Обновил описание темы…

Андрей VG, спасибо за книжку и замечания! Полностью согласен с "прогонами" и, в целом, качеством и точностью сравнений.
bedvit, благодарю за тесты! Пытался задействовать в сравнении "продвинутые" коллекции, но не получилось к ним обратиться…
Изменено: Jack Famous - 27.09.2018 12:16:59
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал: словари тут опять капитально проигрывают, так что пока вижу смысл их использовать только для создания уникальных списков
А если нужно создать массив уникальных, по какому нибудь признаку, массивов? Может Словари не сразу 'в топку'?
Цитата
Я научился создавать массив массивов
Попробуйте создать Словарь Массивов.
Просто Ваше безапелляционное 'только' несколько удивило.  ;) . Для каждой задачи - свой инструмент
В ЭТОЙ теме, на скорую руку...
Изменено: Sanja - 30.09.2018 12:03:54
Согласие есть продукт при полном непротивлении сторон
 
Цитата
Sanja: Может Словари не сразу 'в топку'?
ну конечно нет - ничего радикального (вы меня неправильно поняли). Я ж сказал "пока что" - значит просто не сталкивался с такого рода задачами, ведь
Цитата
Sanja: Для каждой задачи - свой инструмент
Тем более, что для того, чтобы
Цитата
Sanja: создать массив уникальных, по какому нибудь признаку, массивов
словари подходят как нельзя лучше. Я их как раз и "оставил" для работы с уникальными)))
Цитата
Sanja: Попробуйте создать Словарь Массивов
попробую и обновлю тут  ;)
Изменено: Jack Famous - 30.09.2018 12:17:30
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Sanja написал:
Попробуйте создать Словарь Массивов.
И в чем проблема?
Код
Sub Словарь_Массивов()
    Dim Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    Dim Arr, i&, a, s, d
    For i = 1 To 3
        Arr = Range("Мас" & i).Value
        Dict("Мас" & i) = Arr
    Next i
    a = Dict("Мас1")
    s = Dict("Мас2")
    d = Dict("Мас3")
End Sub
 
Цитата
Михаил С. написал: И в чем проблема?
Михаил, это был не вопрос. Это было руководство к дерзанию для Jack Famous,
В том сообщении есть ссылка на мое решение
Изменено: Sanja - 30.09.2018 15:59:20
Согласие есть продукт при полном непротивлении сторон
 
Цитата
Sanja написал:
руководство к дерзанию
дТерзанию :-)
Изменено: БМВ - 30.09.2018 16:25:01
По вопросам из тем форума, личку не читаю.
Страницы: 1
Наверх