Страницы: 1 2 След.
RSS
Как быстрее работает: создать массив данных и потом его обрабатывать или брать данные с листа
 
Добрый вечер!  
Собственно, название темы сама говорит за себя. Я работаю с большим объемом данных. Коллеги утверждают что для обработки информации правильней стачала из таблицы сформировать массив, а после из него циклом вытягивать нужную информацию. У меня создается впечатление,что действуя таким образом мы задваиваем работу: сначала данные попадают в массив, а потом из массива в мою таблицу.    
Вопрос: Кто прав? Если я, то для чего нужны массивы?
 
я буквально неделю назад перегонял тут на форуме не очень-то и объемную задачку (порядка нескольких десятков тысяч значений) в массивы.    
ускорение обработки данных составило около 200 раз, включая операции туда-сюда-копирования.    
правда, большинство формул на листах были простые, не массивные и без сложных функций.  
 
если для Вас это несущественно, то можно не заморачиваться.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
А если отбор в массив идет по критерию, а не укзанием на столбцы? Как правильно задавать массивы?
 
Ещё вопрос. Что такое формула? Возьмем ВПР. В столбце А:А критерии. К ним нужно подтянуть данные из таблицы. Это можно сделать с помощью цикла, можно с помощью формулы ВПР.  
При использовании циклов идет очень сильное потребление оперативной памяти. При формуле - загрузка процессора до 100% на длительное время (Обе таблицы чуть больше 100000 строк).  
На моем компе формулой получается в 5 раз быстрее, значит методы обработки данных разные.  
Вопрос: Каков принцип работы формул?  
Если есть источник информации, киньте пож-ста ссылку.
 
{quote}{login=Leo}{date=05.06.2011 11:30}{thema=}{post}А если отбор в массив идет по критерию, а не укзанием на столбцы? Как правильно задавать массивы?{/post}{/quote}  
Забираем все данные в первый массив, бежим по нему. Данные, удовлетворяющие заданным условиям, отбираем во второй массив. А уже со вторым массивом работаем. В любом случае работа по массиву будет быстрее.
 
продолжим пример с ВПР? :)  
 
"за всех не скажу" (с), но у меня часто получается, что на листе требуется много формул ВПР, ищущих точное соответствие в одном источнике, причем источник этот не отсортирован.  
соответственно, четвертым аргументом ВПР() приходится указывать ЛОЖЬ  
 
если тупо загнать источник в массив и реализовать на VBA аналог ВПР() на этом массиве, то да - придётся пользовать цикл по всему массиву (или, если нашли, то можно выйти раньше).  
однако, намного более оптимальным вариантом будет загнать источник в массив, отсортировать этот массив и использовать не тупой перебор, а метод бинарного поиска по отсортированному массиву.    
также можно и коллекции или словари использовать, но не обязательно.  
выигрыш может быть в разы, особенно на больших массивах.  
 
вывод - не надо торопиться делать выводы :)  
 
пс. если же более быстрый вариант какой-либо функции в VBA реализовать не удаётся, то кто нам мешает чуть-чуть сжульничать и использовать WorksheetFunction? :) правда, там не все функции есть.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
{quote}{login=The_Prist}{date=05.06.2011 11:25}{thema=}{post}Работа на массивах всегда будет быстрее, если правильно разработаны алгоритмы.    
При обращении к ячейкам мы всегда обращаемся к объектной модели другого приложения(для VBA Excel - это сторонне приложение).{/post}{/quote}  
 
соглашусь. Если хочешь убедиться сам, можешь попробовать оба способа,зафиксировав время выполнения каждого.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
...т.е.:  
 
Redim y(65536)  
For q = 1 to 65536  
у(q)=Cells(q,1)  
next  
 
или  
 
Redim y(65536)  
vR = Range(Cells(1,1),Cells(65536,1)).Value  
 
For q = lBound(vR,1) to Ubound(vR,1)  
y(q)= vR(q,1)  
Next  
 
поправьте меня, если ошибаюсь. Второй способ быстрее)
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Сперва помещение данных в массив 1-ым способом, затем вторым)  
 
И это только запись в массив.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Я что-то похожее мерил - получилось около 40 раз ускорение. Только взять данные, изменить и поместить назад или рядом.
 
nerv, pbar всё портит :0  
Померил скорость с баром:  
 
0.90625    
0.453125    
и без:  
0.359375    
0.015625
 
{quote}{login=Hugo}{date=06.06.2011 01:34}{thema=}{post}nerv, pbar всё портит :0  
Померил скорость с баром:  
 
0.90625    
0.453125    
и без:  
0.359375    
0.015625{/post}{/quote}  
 
С пбаром медленее) Визуализация. Он для того, чтобы пользователь видел ход выполнения программы и в этом случае, кстати, не очень уместен : )
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Ну это я сказал не как в укор, а чтоб начинающим понятно было.  
Визуализация тоже имеет право на жизнь - хотел тут один древний код переделать, где ещё не отключал обновление экрана - так юзер воспротивился. Говорит - сижу, отдыхаю десяток секунд, смотрю, как красиво скачут и изменяются ячейки, переключаются листы. Завораживает :)  
И супер скорость ему не нужна - руками день делать, так что десяток секунд никакой роли не играет, задача раз в неделю/месяц...  
Другое дело если данных много, обрабатывать нужно часто, и 1 минута или 40 минут - это уже чувствительно.
 
{quote}{login=Hugo}{date=06.06.2011 01:47}{thema=}{post}Ну это я сказал не как в укор, а чтоб начинающим понятно было.  
Визуализация тоже имеет право на жизнь - хотел тут один древний код переделать, где ещё не отключал обновление экрана - так юзер воспротивился. Говорит - сижу, отдыхаю десяток секунд, смотрю, как красиво скачут и изменяются ячейки, переключаются листы. Завораживает :)  
И супер скорость ему не нужна - руками день делать, так что десяток секунд никакой роли не играет, задача раз в неделю/месяц...  
Другое дело если данных много, обрабатывать нужно часто, и 1 минута или 40 минут - это уже чувствительно.{/post}{/quote}  
 
я понял)  
Кстати, если последнюю цифру в строке пбара со 100 изменить на 255 должно выполняться быстрее) (частота обновления)
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Огромное спасибо всем. Особая благодарность Юрию, за совет из массива в массив, завтра опробую на работе:)  
Очень заинтересовал совет Ikki, но мои познания массивов еще не позволяют сортировать данные внутри них. Хотя, описание результата весьма радует:)  
 
Давайте рассмотрим пример. Я сделал миниатюру. Чтобы отследить скорость достаточно скопировать нижнюю строчку двух первых столбцов на 10000 строк(только критерии лучше брать не 2, а другой). В файле 2 макроса. Один без массива, другой с массивом. Работают одинаково быстро.    
Возможно коряво написал макрос с массивом. Покажите как ускорить обработку.  
 
Суть макроса. У критерия может быть много свойств. И мы их собираем в одну ячейку через ;
 
{quote}{login=Leo}{date=06.06.2011 10:25}{thema=}{post}В файле 2 макроса. Один без массива, другой с массивом. Работают одинаково ... {/post}{/quote}  
 
ага)))
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Уж сколько раз прокалываюсь, пытаясь нажать кнопку на скрине :-)
 
{quote}{login=Юрий М}{date=06.06.2011 10:39}{thema=}{post}Уж сколько раз прокалываюсь, пытаясь нажать кнопку на скрине :-){/post}{/quote}  
 
дядь, Юр))) ^_^
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Буквально на днях на 90% похожую задачу делали - там два варианта, правда тоже очень похожих:  
http://www.programmersforum.ru/showthread.php?t=150405  
Сейчас попробую переделать...  
А у Вас на массивах в корне неправильно сделано - там ведь всё так просто делается, не поверите...
 
А ошибки (на скрине) не будет, если файл пример 5.xls :)
 
С минимальными переделками того кода:  
 
 
Sub Hugo()  
 
Dim a, aa(), i&, j&, u&, s$  
a = [a1].CurrentRegion.Value
ReDim aa(1 To UBound(a, 1), 1 To 2)  
 
With CreateObject("Scripting.Dictionary")  
   .CompareMode = 1  
   For i = 1 To UBound(a, 1)  
       s = Trim(a(i, 1))  
       If Len(s) Then  
       If Not .Exists(s) Then  
           j = j + 1: .Item(s) = CStr(j)  
           aa(j, 1) = s: aa(j, 2) = CStr(a(i, 2))  
           Else  
           u = .Item(s): aa(u, 2) = aa(u, 2) & ", " & a(i, 2)  
       End If  
       End If  
   Next  
End With  
 
Workbooks.Add.Sheets(1).[a1:b1].Resize(j) = aa
 
End Sub  
 
 
Но правда это немного не то, что нужно было - тут извлекаются уникальные, и к ним собирается строка. Но на массиве (и словаре) :)  
А вообще именно эту задачу делает UDF VLOOKUPCOUPLE() из копилки:  
http://www.planetaexcel.ru/forum.php/plex.php?thread_id=16564
 
Мда, не учел что книга будет менять название. Каюсь)
 
{quote}{login=Hugo}{date=06.06.2011 10:58}{thema=}{post}С минимальными переделками того кода:  
 
 
Sub Hugo()  
 
Dim a, aa(), i&, j&, u&, s$  
a = [a1].CurrentRegion.Value
ReDim aa(1 To UBound(a, 1), 1 To 2)  
 
With CreateObject("Scripting.Dictionary")  
   .CompareMode = 1  
   For i = 1 To UBound(a, 1)  
       s = Trim(a(i, 1))  
       If Len(s) Then  
       If Not .Exists(s) Then  
           j = j + 1: .Item(s) = CStr(j)  
           aa(j, 1) = s: aa(j, 2) = CStr(a(i, 2))  
           Else  
           u = .Item(s): aa(u, 2) = aa(u, 2) & ", " & a(i, 2)  
       End If  
       End If  
   Next  
End With  
 
Workbooks.Add.Sheets(1).[a1:b1].Resize(j) = aa
 
End Sub  
 
 
Но правда это немного не то, что нужно было - тут извлекаются уникальные, и к ним собирается строка. Но на массиве (и словаре) :)  
А вообще именно эту задачу делает UDF VLOOKUPCOUPLE() из копилки:  
http://www.planetaexcel.ru/forum.php/plex.php?thread_id=16564{/post}{/quote}  
 
 
Спасибо! Буду разбираться)
 
Sub tt()  
   Dim a, b, i As Long, ii As Long  
   a = [a1].CurrentRegion.Value
   [f1] = "." 'военная хитрость :)
   b = [e1].CurrentRegion.Value
   For i = 1 To UBound(b)  
       For ii = 1 To UBound(a)  
           If b(i, 1) = a(ii, 1) Then  
               If Len(b(i, 2)) Then  
                   b(i, 2) = b(i, 2) & "; " & a(ii, 2)  
               Else  
                   b(i, 2) = a(ii, 2)  
               End If  
           End If  
       Next ii, i  
       [e1].CurrentRegion.Value = b
   End Sub  
 
 
Без "хитрости" можно обойтись, но тогда нужно другой параллельный массив вводить, куда собирать строки, и потом его только и выгружать. Но это лениво, да и код только усложнит... А содержимое массивов смотрите в окне Locals.
 
{quote}{login=Юрий М}{date=06.06.2011 10:39}{thema=}{post}Уж сколько раз прокалываюсь, пытаясь нажать кнопку на скрине :-){/post}{/quote}  
А так-же бывают попытки уменьшить громкость речи окружающих пультом от телевизора и открыть дверь подъезда пультом автосигнализации?!:)
 
Здесь есть макрос ВПР_для_больших  
 
Работает на словаре. Предназначение - большие массивы данных
 
ну и немного других функций
 
leo, в вашем файле много разных вызовов форм, которых в вашем файле нет, например:  
 
ChangeFormat.Show  
UserForm5.Show  
UserForm6.Show  
UserForm8.Show  
UserForm9.Show  
UserForm11.Show  
UserForm13.Show  
UserForm14.Show  
UserForm15.Show  
 
   UserForm14.Label3 = ActiveWorkbook.Name  
   UserForm14.Label4 = ActiveSheet.Name  
 
UserForm4.Label9.Caption = "xls"  
UserForm14.ListBox1.AddItem (Kniga)  
 
Не понятно, зачем выкладывать столько лишнего мусора.    
У вас в коде 11 процедур, куча функций, 285 строк кода  
 
Люди начнут тестировать, а там одно ошибки полезут с вашими отсутствующими формами и т.д.
 
И кстати "ВПР_для_больших" я там не нашёл :(  
Правда не очень-то и искал - так, просмотрел перематывая... не нашёл.
 
Игорь, подскажу - Alt+F8 ))    
но я даже и вникать не стал, мы с тобой уже столько таких "впр-ов" из разных баз написали...  
 
но может кому-то этот файл от Leo поможет, не знаю
Страницы: 1 2 След.
Читают тему
Наверх