Страницы: 1
RSS
Удалить строку из массива
 
Добрый день, коллеги,
Подскажите, пожалуйста, эффективный код на удаление строки из двумерного массива (последующие строки "смещаются" вверх на 1).
На сколько я знаю, redimpreserve можно использовать только не выше двумерного массива?
 
Цитата
Oleg пишет:
На сколько я знаю, redimpreserve можно использовать только не выше двумерного массива?
Не верное утверждение. Redim не удаляет элементы, он изменяет размер массива, при чем только по последней(!) размерности. Вообще именно удалить "строку" массива будет проблематично (если вообще возможно), но проблему можно решить по другому. Допустим так - скопировать в другой массив только нужные строки.
Код
Sub DeletingEmptyValuesFromArray(ByRef vaBasic() As Variant, Optional ByVal ColumnNum As Long = 1)
'Удаление пустых строк в массиве
'Передаваемый массив должен быть динамическим, двумерным
'ColumnNum - номер столбца по которому проверяется пустое значение

Dim i As Long, j As Long, n As Long
Dim vaTemp() As Variant
'Копируем массив во временную переменную
vaTemp = vaBasic
'Считаем количество непустых строк в массиве
n = 0
For i = 1 To UBound(vaTemp, 1)
    If Not IsEmpty(vaTemp(i, ColumnNum)) Then n = n + 1
Next

If n = 0 Then Erase vaBasic: Exit Sub

'Определяем новый размер массива
ReDim vaBasic(n, UBound(vaTemp, 2))
'Заполняем массив непустыми строками
n = 0
For i = 1 To UBound(vaTemp, 1)
    If Not IsEmpty(vaTemp(i, ColumnNum)) Then
        n = n + 1
        For j = 1 To UBound(vaTemp, 2)
            vaBasic(n, j) = vaTemp(i, j)
        Next
    End If
Next
End Sub
Изменено: LVL - 03.07.2014 10:05:01
 
LVL, спасибо, в коде разобрался. Единственное что озадачило - я думал в массивах с 0, а не с 1 элемента идет счет если задавать так redim (5), а не так redim (1 to 5).
А не быстрее будет перезаписать строку i (удаляемую) строкой i+1, а следующую i+1 заменить i+2 и до конца. Потом "обрезать" массив на 1?
Хотя, наверное, при большом кол-ве удаляемых строк, это будет хуже работать. Изначально я все эти процедуры выполнял с данными листа, но очень уж медленно выходит.
 
Цитата
Oleg пишет: А не быстрее будет перезаписать строку ... . Потом "обрезать" массив на 1?
создать пустой массив и в него перекинуть нужное - всегда быстрее чем перезаписывать все строки в нём со смещением...
его потом обрезать, думаю, не представляется возможным... сначала - обрезать (что надо) т е ReDim задать новую размерность - потом перекидывать...
имхо (насколько мне позволили мои знания)... или знающие поправят
Изменено: JeyCi - 04.07.2014 11:13:44
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Цитата
Oleg пишет: я думал в массивах с 0, а не с 1 элемента идет счет
По умолчанию да, но в зависимости от ситуации можно считать и от одного, в самом начале модуля пишите Option Base 1 и отсчёт будет начинаться с 1. Соответственно это справедливо при инициализации массива, если явно не указаны его границы.
 
Навеяло...
Как математик и инженер решают одну и ту же задачу: вытащить из доски наполовину забитый гвоздь...
Инженер вытаскивает гвоздь.
Математик забивает его до конца и затем решает задачу в общем случае.
Изменено: Мотя - 04.07.2014 11:41:50
 
Цитата
Oleg пишет: Потом "обрезать" массив на 1?
Читайте внимательно. Строки двумерного массива - это первая размерность, столбцы - вторая. Вы можете изменять только вторую размерность, т.е. столбцы. Можете извратиться и транспонировать массив, если это уже так необходимо, тогда вторым измерением станут строки
F1 творит чудеса
 
Вот сколько пишу макросы - никогда не нужно было удалять строку из двумерного массива... Зачем?
Всегда можно сделать как-то иначе. Например запомнить в коллекции/словаре номера нужных (или ненужных) строк, затем в финале переложить в новый массив только нужные строки.
Это если это удаление Вы хотите делать неоднократно в цикле. Если один раз (т.е. при одном анализе массива) - то просто перекладывайте нужные строки в аналогичный по размеру пустой массив, хвост которого откинете при выгрузке на лист.
Ну конечно если из миллиона нужно отобрать 100 - то это расточительно, тогда используйте коллекцию номеров :)
Изменено: Hugo - 04.07.2014 11:52:09
 
Цитата
Максим Зеленский пишет: Строки двумерного массива - это первая размерность, столбцы - вторая. Вы можете изменять только вторую размерность, т.е. столбцы. Можете извратиться и транспонировать массив, если это уже так необходимо, тогда вторым измерением станут строки
А где написано, что первое измерение - это строки, а второе - столбцы? Тут каждый решает сам. В крайнем случае, можно сделать как-то так:
Код
Dim ArrBase(5) As Variant, ArrInSide(4) As String
ArrBase(1) = ArrInSide   'Заносим "строку" в массив
... 'ещё разный код по заполнению строк
For Row = 0 To UBound(ArrBase) 'Перебор строк
    For col = 0 To UBound(ArrBase(Row)) 'Перебор столбцов
          a = ArrBase(Row)(col) 'Получаем значение из ячейки строки
    Next col
Next Row
Если не принципиальна последовательность данных (строк), то можно переместить последнюю на место удаляемой и удалить освободившееся место. Если же операция часто выполняемая, то следует менять алгоритм, минимизируя перемещения и удаления строк.
Изменено: Skif-F - 04.07.2014 12:49:15
 
Цитата
Skif-F пишет: А где написано, что первое измерение - это строки, а второе - столбцы?
да нет, конечно нигде, но, если не ошибаюсь, по умолчанию, при загоне данных с листа, создается двумерный массив, где первое измерение - строки, а второе - столбцы.
ArrBase(1) = ArrInSide 'Заносим "строку" в массив - даже не подозревал, что так можно... пошел думать
F1 творит чудеса
Страницы: 1
Читают тему
Наверх