Страницы: 1
RSS
Изменить размер заполненного массива по количеству элементов. Правила Redim Preserve для массивов разных размерностей
 
Доброго времени суток, Планетяне!

Вот в этой теме столкнулся с проблемой "ридимопресервания" 2х массива  :D

Процесс:
1. ищу совпадения (строки "r", может быть несколько) по заданному столбцу
2. Если совпадение есть, то забираю значения ячеек нескольких "N" столбцов по этой строке
3. Продолжаю поиск

Первое, что приходит в голову, это собирать двумерный массив arr(1 To r, 1 To N). Но для этого нужно объявить его с запасом, то есть Redim arr (1 To ROWS, 1 To N), где ROWS - все проверяемые строки. Проблема возникает, при попытке после отбора сделать Redim Preserve arr(1 To r, 1 To N), т.к. редимить можно только последнюю размерность. В той теме я обошёл это, собирая всё в 1х массив, редимя его и, потом, в цикле, восстанавливая структуру по блокам.
Как сделать быстрее, проще и правильнее в этом случае?

Планирую собрать в этой теме примеры с разными размерностями и нюансами их использования
Изменено: Jack Famous - 13.08.2018 11:18:27
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
1) Если  исходный массив больше не будет использоваться можно его перезаписывать с применением дополнительной  переменной счетчиком, которая увеличивается при выполнении определенного условия.
2) Либо объявить массив размером с исходником, заполнять так же как и в первом случае с использованием переменной  (счетчик), далее переносить на лист указывая размерность по вертикали равную переменной счетчику.
3) можно и ReDim пресервить перевернув массив а потом просто транспонировать циклом, транспонирование больших массивов займет время, но не думаю что это критично.
Изменено: Nordheim - 09.08.2018 11:05:43
"Все гениальное просто, а все простое гениально!!!"
 
коллекция - это условный аналог массива неопределнного размера, воспользутесь ее возможностями.
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Nordheim, Ігор Гончаренко, спасибо, ребят! А можно примеры в виде кода? Хоть мааааахонькие  :)
что ваш личный опыт говорит?
Цитата
Nordheim: можно и ReDim пресервить перевернув массив а потом просто транспонировать циклом
тоже подумал об этом, но в этом случае выигрыш вряд ли будет…
Изменено: Jack Famous - 09.08.2018 11:09:31
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Скрытый текст

Цитата
Jack Famous написал:
выигрыш
и ReDim Preserve  касаемо оптимизации по времени выполнения понятия несовместимые
Изменено: Nordheim - 09.08.2018 15:31:28
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, реализация через словарь - буду пробовать. Спасибо!  :)
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Nordheim написал:
ReDim Preserve  касаемо оптимизации по времени выполнения понятия несовместимые
Как обычно на свой сугубо не макрушный взгляд, а нужно ли тянуть все в массив. Возможно скорость работы прямо с листом не будет сильно меньше.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
а нужно ли тянуть все в массив
Все зависит от количества обращений к листу. Если их очень много, то скорость обработки вырастает в разы.
У меня был макрос обрабатывающий (сверяющий 2 листа) хитрым образом выводя в отчет еще 3 листа. Написан был с обращением к листу так там время обработки было от 2 до 6 мин. Запихнул обработку в массив время обработки сократилось от 6 до 21 сек. Как то так  :D
Изменено: Nordheim - 09.08.2018 12:01:21
"Все гениальное просто, а все простое гениально!!!"
 
Еще вариант:
1. Собираем в словарь номера строк, удовлетворяющих условию. (в примере - это непустые значения 1-го столбца).
2. Определяем уже известную размерность итогового массива
3. Собираем итоговый массив из выбранных строк исходного массива.
Т. е примерно так:
Код
Sub qq()
    Dim i As Long, j As Long, a(), b(), z, q
    Set z = CreateObject("Scripting.Dictionary")
    a = [A1:C20].Value 'Пусть это исходный массив
    For i = 1 To UBound(a, 1)
        If a(i, 1) <> "" Then z(i) = ""
    Next
    ReDim b(1 To z.Count, 1 To UBound(a, 2)): i = 0
    For Each q In z.Keys
        i = i + 1
        For j = 1 To UBound(a, 2): b(i, j) = a(q, j): Next
    Next
End Sub
Изменено: SAS888 - 10.08.2018 06:06:04
Чем шире угол зрения, тем он тупее.
 
Цитата
Nordheim : зависит от количества обращений к листу
вот это в точку! При постоянном обращении, выигрыш огромен  ;)

SAS888, вот это тоже очень крутой вариант! Спасибо! Он даже ближе, чем словари, т.к. с ними работал меньше, но пора впрягаться)))
Изменено: Jack Famous - 09.08.2018 12:10:24
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
Он даже ближе, чем словари
Вариант со словарем ближе чем словари, это как?  8-0
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim: это как?
тупо - согласен)) просто я мысленно словари на массивы заменил)))
Типа, собираем строки, а потом комплектуем массив известной размерности. Чуть более понятно, но с 2мя (отдельными не вложенными) циклами, что, наверное, проиграет в скорости.
Решения всякие нужны, решения всякие важны!  :)
Изменено: Jack Famous - 09.08.2018 12:19:57
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Nordheim написал:
Все зависит от количества обращений к листу
Все верно, просто часто в массив загоняют и малоразмерные области, типа по привычке, потом вах надо изменить размерность и начинается танец с бубном, а там разница по скорости будет совсем скромная. Для каждой задачи свое решение.
По вопросам из тем форума, личку не читаю.
 
Цитата
Jack Famous написал:
с 2мя (отдельными не вложенными) циклами
Если объемы большие то это не вариант. Если не привычны словари, то можно коллекции использовать там принцип вроде тот же, только уникальность обрабатывается через
Код
On Error Resume Next
, а в условии прописывается
Код
If Err.Number = 0 then 
'Цикл переноса
Err.Clear
End If
.
Вроде как то так.
Изменено: Nordheim - 09.08.2018 12:30:51
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
БМВ: Для каждой задачи свое решение
приветствую! Прописная истина  :idea:
Цитата
Nordheim: Если не привычны словари…
, то надо их изучать, как и коллекции и прочее :D потом использовать в зависимости от задачи, как и сказал БМВ  ;)
за пример спасибо  :)
Изменено: Jack Famous - 09.08.2018 12:33:04
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Можно, в этом случае, пользовать только массивы:
Код
Sub uuu()
    Dim i As Long, j As Long, a(), b(), z&(), q&, s&
    a = [A1:C20].Value 'Пусть это исходный массив
    ReDim z(1 To UBound(a, 1)) ' массив номеров строк (размер с запасом) '
    For i = 1 To UBound(a, 1)
        If a(i, 1) <> "" Then q = q + 1: z(q) = i
        ''''If a(i, 1) = Что_ищем Then q = q + 1: z(q) = i
    Next
    ReDim b(1 To q, 1 To UBound(a, 2))
    For i = 1 To q
        s = s + 1
        For j = 1 To UBound(b, 2): b(s, j) = a(z(i), j): Next
    Next
    [F1].Resize(q, UBound(b, 2)).Value = b
End Sub
 
Цитата
С.М. написал:
Можно, в этом случае, пользовать только массивы:
Но массивы не исключают дубликаты, что делают словари и коллекции.
"Все гениальное просто, а все простое гениально!!!"
 
А причём здесь исключение дубликатов ?
Цитата
Jack Famous написал #1:
Процесс:1. ищу совпадения (строки "r", может быть несколько) по заданному столбцу2. Если совпадение есть, то забираю значения ячеек нескольких "N" столбцов по этой строке3. Продолжаю поиск
Изменено: С.М. - 09.08.2018 15:14:33
 
С.М., спасибо за пример, Согласен — дублей среди номеров строк быть не может и так…
Изменено: Jack Famous - 13.08.2018 11:21:21
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
В связи с тем что нужно сравнивать именно значения, и переносить независимо есть ли дубли, переделал примеры в сообщении№5
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, спасибо  :)
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Nordheim написал #20:
В связи с тем что нужно сравнивать именно значения
Ладно. Мир-труд-жвачка ! (с)
Я понял задачу Jack Famous, также как SAS888 в #9. У нас абсолютно одинаковый результат, но разные инструменты.
 
Вариант с использованием коллекции. Чуть проще, т. к. выбор элементов коллекции осуществляется по указателю цикла.
Как быстрее - не проверял.
Код
Sub qq()
    Dim i As Long, j As Long, a(), b(), z As New Collection
    a = [A1:C20].Value 'Пусть это исходный массив
    For i = 1 To UBound(a, 1)
        If a(i, 1) <> "" Then z.Add i
    Next
    ReDim b(1 To z.Count, 1 To UBound(a, 2))
    For i = 1 To z.Count
        For j = 1 To UBound(a, 2): b(i, j) = a(z(i), j): Next
    Next
End Sub
Чем шире угол зрения, тем он тупее.
 
А если этот цикл
Код
    For i = 1 To z.Count
        For j = 1 To UBound(a, 2): b(i, j) = a(z(i), j): Next
    Next

заменить на этот
Код
i=0
For  Each ikey In z
    i=i+1
    For j =1 to UBound(a,2)
        b(i,j)=a(val(ikey),j)
    Next j 
next ikey

Сталкивался с перебором элементов коллекции, через
Код
For .....Next 
получается дольше чем через
Код
For Each ....Next

но и объемы конечно имеют значение.
Изменено: Nordheim - 10.08.2018 08:13:36
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim: получается дольше
согласен — стараюсь использовать For i=…To… только когда нужен этот i внутри цикла
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
только когда нужен этот i внутри цикла
Тут по любому нужен i , что бы изменялась строка принимающего массива, просто перебор коллекции быстрей осуществляет цикл
Код
For Each ..... Next
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim: Тут по любому нужен i
проглядел, что вы внутри цикла увеличиваете счётчик — то есть можно ВСЕГДА заменять таким образом??? Это вообще законно?  :D
Изменено: Jack Famous - 10.08.2018 11:13:35
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
Это вообще законно?  
А почему нет?  :D
В Словарях только этот цикл и использую, а если делать с помощью For ...Next (в словарях), так там прям танцы с бубнами, в одних скобках запутаешься.
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, век живи - век учись)) про выгоду For Each слышал не раз, а то что её можно всегда использовать таким образом - не допёр  :D
Спасибо вам большое!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Страницы: 1
Наверх