как удалить элемент из массива

Автор gnus, 14 декабря 2013, 08:16

0 Пользователи и 1 гость просматривают эту тему.

gnus

Собственно вот как удалить определенный элемент из массива, например, одномерного?

calc4fem

присвоить ему другое значение ?

JohnSUN

Существует несколько алгоритмов для решения этой задачи.
1. "Затратный" - перезапись нужных (оставшихся) значений в новый массив меньшего размера с последующим переприсвоением старому массиву нового значения (указателя на новый массив). Такой способ использован, например, в процедуре RemoveListboxItemByName (модуль Listbox стандартной библиотеки макросов Tools)
2. "Долгий" - перезапись в цикле оставшихся элементов массива ("хвоста") на новое место и после этого переопределение размера массива (ReDim Preserve)
3. "Продвинутый" ("Заумный") - сразу отказаться от использования массива и создавать списки или деревья значений. Алгоритмы исключения элементов для этих случаев хорошо расписаны, например, у Н.Вирта в "Алгоритмы + структуры данных = программы"
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

gnus

#3

Sub arrayTest
Dim i as Date
Dim n as Integer
Dim arr()

countDates=0

for i="02.09.2013" to "07.09.2013"
redim preserve arr(countDates) 'так как календарный период изначально не известен, размер приходится переопределять
arr(countDates)=i
countDates=countDates+1
next

for n=LBound(arr) to UBound(arr)
Select Case arr(n)
 Case "03.09.2013"
  print "праздник 3 сентября"
 Case "06.09.2013"
  print "праздник 6 сентября"
End Select
next
End Sub


Т.е. в такой ситуации (нужно удалить определенные даты из списка, праздничные дни) можно воспользоваться "долгим" способом? Как можно переписать?

gnus

и еще, если не затруднит, может продемонстрируете пример создания списка (синтаксис)?

JohnSUN

Можно так:
Sub arrayTest
Dim i as Date
Dim n as Integer
Dim ind as Integer
Dim cntEl as Integer
Dim arr()
Dim excludeDates
countDates=0

for i="02.09.2013" to "07.09.2013"
redim preserve arr(countDates) 'так как календарный период изначально не известен, размер приходится переопределять
arr(countDates)=i
countDates=countDates+1
next i

excludeDates = Array(CDate("03.09.2013"), CDate("06.09.2013"))

cntEl = UBound(arr)
for n=LBound(arr) to cntEl
REM Можно было оставить Select Case, но праздников может быть много
REM С массивом в этом случае работать проще
ind = IndexOf(excludeDates, arr(n))
if ind>-1 Then
RemoveItem(arr, n)
cntEl = cntEl - 1 ' Массив стал меньше, значит и цикл будет короче
EndIf
next n
End Sub

REM Функция фозвращает индекс (положение в одномерном массиве
REM sourceArr) первого встреченного элемента,
REM значение которого совпадает с Item, или -1 есле его нет
Function IndexOf(sourceArr, Item)
Dim MaxIndex as Integer
Dim i as Integer
IndexOf() = -1 ' Уверены в неудаче - элемент не будет найден
MaxIndex = Ubound(sourceArr())
For i = 0 To MaxIndex
If Item = sourceArr(i) Then
IndexOf() = i ' Нашли совпадение
Exit Function
End If
Next i
End Function

REM Процедура удаляет из массива sourceArr
REM элемент с индексом index
Sub RemoveItem(sourceArr, index%)
Dim i%, l%
l = UBound(sourceArr)-1
For i = index To l
sourceArr(i)=sourceArr(i+1)
Next i
ReDim Preserve sourceArr(l)
End Sub
Цитата: gnus от 27 декабря 2013, 15:00
и еще, если не затруднит, может продемонстрируете пример создания списка (синтаксис)?
Давай уже в следующем году, ладно? Там не сложно, но нужно внимательно выписывать все эти присвоения-переприсвоения... А времени сейчас, сам понимаешь, не особо
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

gnus

Ловко у тебя получается). Буду изучать. С Новым годом.

VlhOwn

ИМХО, не нужно изобретать велосипед - используйте не Basic, а Python, и все динамические структуры данных (списки, кортежи, словари) будут в вашем распоряжении. Трудозатраты на изучение Python с лихвой покроются необходимостью моделировать динамику на Basic.

gnus

#8
Это, кстати, идея. Python еще не пробовал. Но у меня в libreoffice при открытии Макросы python кнопка Создать не активна. Похоже, что python не до конца прикрутили к офису. Его придется писать в другой среде, это не очень удобно, хочется использовать кнопочки всякие, чекбоксы, выпадающие списки в документах офиса...  Вас тоже с наступающим)

Hasim

А надо ли удалять?
Есть подозрение, что нужно просто указать, какие дни в году рабочие, какие выходные, а какие праздничные?
Обсуждается метод решения неизвестно какой изначально задачи.

gnus

Ну, удалять, наверное, необязательно. Просто в дальнейшем нужно будет взять рабочие дни и вставить в таблицу (они еще кстати по дням недели будут фильтроваться).