Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/37: Рейтинг темы: голосов - 37, средняя оценка - 4.59
4 / 4 / 1
Регистрация: 21.05.2012
Сообщений: 12

Erase для массива, являющегося элементом коллекции

21.05.2012, 18:08. Показов 7903. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Некоторое дополнение к предыдущей теме "Присвоение значения элементу коллекции Col.Item(N)(2) = 34". Суть проблемы в том, что после добавления нового элемента коллекции Collection, которому назначается ссылка на динамический массив, использование оператора Erase не приводит к освобождению памяти от этого массива.

Visual Basic
1
2
3
4
5
6
7
8
Private Sub Proba()
  Dim Collect As New Collection
  ReDim Arr(1 To 3) As Integer
  Arr(1) = 3: Arr(2) = 4: Arr(3) = 5
  Collect.Add Arr
  Erase Collect.Item(1) '//////////////////////
  Dim B As Integer: B = Collect.Item(1)(2): MsgBox "B = " & VBA.CStr(B)   ' Выводит на экран окно с текстом "B = 4"
End Sub
По логике, при применении оператора Erase к динамическому массиву Arr, которым в данном примере является элемент коллекции Collect.Item(1), этот массив должен уничтожаться. Но этого не происходит, независимо от того объявлен ли этот массив в этой же процедуре или был создан в другой процедуре, либо создан с использованием функции Array(). Не происходит также и обнуление элементов массива в Collect.Item(1), если присвоенный этому элементу коллекции массив Arr() был объявлен не как динамический (Redim), а как статический с использованием директивы Dim. Короче, работа с массивом, являющимся элементом объекта Collection, возможна только на чтение значений элементов из массива (см. последнюю строку примера кода "Dim B As Integer ...").
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.05.2012, 18:08
Ответы с готовыми решениями:

Вызов метода являющегося элементом коллекции
Есть коллекция методов List<object> objects = new List<object>(); objects.Add(new Action(() => SendKeys.Send("{TAB}"))); Пытаемся...

Вызов методов класса, являющегося элементом массива
Достаточно интересная задача попалась: Есть некий массив Обработчиков (Handlers), которые выполняют различные функции конкретно под...

Алгоритм поиска элемента последовательности, не являющегося элементом второй
Доброго времени суток! Выполняя очередную лабораторную по программированию, наткнулся на проблему выбора наиболее быстрого алгоритма для...

6
15155 / 6428 / 1731
Регистрация: 24.09.2011
Сообщений: 9,999
21.05.2012, 18:43
Решение состоит в том, чтобы сделать элементом коллекции не массив, а объект - другую коллекцию (или словарь), или экземпляр пользовательского класса.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
' код модуля класса MyArr
 
Dim arr() As Integer
 
Public Sub EraseArr() 'метод для стирания массива
Erase arr
End Sub
 
Public Sub ArrWrite(indx&, value) 'метод для записи элемента массива
arr(indx) = value
End Sub
 
Public Function ArrRead(indx&) 'свойство, возвращающее элемент массива
ArrRead = arr(indx)
End Function
 
Public Sub ArrRedim(lb&, ub&, Optional pres As Boolean = False) 'метод переопределения размерности массива
If pres Then ReDim Preserve arr(lb To ub) Else ReDim arr(lb To ub)
End Sub
 
'код модуля
 
Sub test()
With New Collection
    .Add New ArrClass 'создание экземпляра класса
    .Item(1).ArrRedim 1, 3
    .Item(1).ArrWrite 2, 34
    MsgBox .Item(1).ArrRead(2) '34
    .Item(1).ArrRedim 1, 5, True
    .Item(1).ArrWrite 5, -3
    MsgBox .Item(1).ArrRead(5) '-3
    .Item(1).EraseArr
End With
End Sub
1
4 / 4 / 1
Регистрация: 21.05.2012
Сообщений: 12
22.05.2012, 00:20  [ТС]
Предлагаемое Казанским решение проблемы вполне приемлемо, если массив не очень большой (мне, например, нужен массив, содержащий 6 измерений), а также пригодно для многомерных массивов. Обращение к элементу массива выглядит почти также, как и при стандартном способе обращения к нему "Arr(1,2,4)" -> ".ArrRead(1,2,4)". Единственным ограничением на использование предлагаемой методики является время выполнения программы. Я протестировал скорость работы при использовании класса и при обычном способе обращения к элементу массива. Естественно, при использовании класса для обращения к элементу массива затраченное время будет больше. А именно, запись в элемент массива выполняется в 3 раза медленнее, чем при обычном способе записи некоторого значения в элемент массива, а чтение в 3,5 раза медленнее. При этом размерность массива почти не влияет на эту скорость.
Кстати, можно использовать особенность присвоения элементу коллекции динамического массива для данных программы, которые требуют статуса "только для чтения".
Спасибо за предложенный вариант решения проблемы.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
22.05.2012, 01:00
Если требуется только Erase, то
второй вариант заключается в удалении элемента и добавление на его место пустого массива.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Private Sub Proba()
Dim Col As New Collection
Dim Arr(3), Empt(3)
Arr(1) = 3: Arr(2) = 4: Arr(3) = 5
Col.Add ("1")
Col.Add Arr
Col.Add ("3")
Col.Remove (2)
Col.Add Empt, , 2
MsgBox Col.Item(2)(1)
End Sub
Единственный тормоз здесь будет сама операция удаления.
2
15155 / 6428 / 1731
Регистрация: 24.09.2011
Сообщений: 9,999
22.05.2012, 01:11
А почему, собственно, коллекция? Работайте с массивом массивов или с массивом переменных пользовательского типа, содержащих массив.
В первом случае все переменные будут типа Variant (что снижает быстродействие), во втором - можно задавать тип:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Type MyType
    i() As Integer
End Type
 
Sub dd()
Dim v(), x, y() As MyType
ReDim v(1 To 2)
ReDim x(1 To 3, 1 To 4)
v(1) = x
v(1)(1, 1) = 5
v(1)(2, 3) = 7
ReDim x(2, 2, 2)
v(2) = x
v(2)(1, 1, 1) = 9
Erase v(1)          'v(1) становится пустым массивом, v(2) остается
 
ReDim y(0 To 1)
ReDim y(0).i(1 To 2, 0 To 1, 0 To 2)
y(0).i(1, 1, 1) = 19
ReDim y(1).i(1 To 5, 0 To 1)
y(1).i(4, 1) = 119
Erase y(1).i           'y(0) остается
End Sub
Я понимаю, что в коллекцию удобнее добавлять и удалять элемент в определенном месте. Но с массивом это тоже возможно.
2
4 / 4 / 1
Регистрация: 21.05.2012
Сообщений: 12
22.05.2012, 01:41  [ТС]
Весьма оригинальное решение, как-то раньше не встречал такого, да и сам не использовал. Особенно необычно объявление:
Visual Basic
1
2
3
4
5
6
7
Dim y() As MyType
...
ReDim y(0).i(1 To 2, 0 To 1, 0 To 2)
с учетом, что тип MyType:
Type MyType
    i() As Integer
End Type
Получается достаточно гибкое решение, хотя запись его, конечно, более громоздка и менее прозрачна, чем при использовании семейства.
Конкретно в моем случае используется структура данных, состоящая из семейств на верхнем уровне с глубиной вложения 3, а на нижнем 6-мерный массив с числом элементов в измерениях от 3 до 12. Я думаю, все-таки, остановлюсь на 1 варианте, а последний возьму на заметку, возможно, когда нибудь и пригодится. Спасибо.
0
15155 / 6428 / 1731
Регистрация: 24.09.2011
Сообщений: 9,999
22.05.2012, 02:21
Лучший ответ Сообщение было отмечено как решение

Решение

Кстати, во втором посте этой темы я весьма коряво написал класс
Можно прописать свойства так, что работа с массивом-элементом коллекции становится почти идентичной работе с массивом-элементом массива.

Этот код класса надо вставить в Блокнот и сохранить как MyArr.cls, а потом импортировать в проект. Код содержит директиву для назначения одного из свойств членом класса по умолчанию. Эта директива не может быть введена с помощью редактора VBA (см. ссылку в комментарии).
Потом код класса можно редактировать в VBE как обычно.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "MyArr"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
 
Dim arr() As Long
 
Property Let Elem(i&, x&)
arr(i) = x
End Property
 
Property Get Elem&(i&)
Attribute Elem.VB_UserMemId = 0
'http://www.cpearson.com/excel/DefaultMember.aspx - член класса по умолчанию
Elem = arr(i)
End Property
 
Public Sub EraseArr() 'метод для стирания массива
Erase arr
End Sub
 
Public Sub RedimArr(lb&, ub&, Optional pres As Boolean = False) 'метод переопределения размерности массива
If pres Then ReDim Preserve arr(lb To ub) Else ReDim arr(lb To ub)
End Sub
 
Property Get Ubnd()
Ubnd = UBound(arr)
End Property
 
Property Get Lbnd()
Lbnd = LBound(arr)
End Property
Пример работы с коллекцией экземпляров класса:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Sub test()
Dim cl As Collection, i&, x
Set cl = New Collection
cl.Add New MyArr            'создание экземпляра класса
cl(1).RedimArr 1, 3
For i = 1 To 3
    cl(1)(i) = i * 10       'cl(1)(i) это cl(1).Elem(i), Elem - член класса по умолчанию
Next
 
cl.Add New MyArr, Before:=1 'создание еще одного экземпляра класса
cl(1).RedimArr -1, 2
For i = -1 To 2
    cl(1)(i) = i * 100
Next
GoSub print_collection
 
With cl(2)                      'добавление элемента в массив
    .RedimArr 1, .Ubnd + 1, True
    .Elem(.Ubnd) = 77           'здесь Elem приходится указывать
End With
GoSub print_collection
 
cl(1).EraseArr                  'стирание массива
cl(1).RedimArr 0, 3, True
GoSub print_collection
 
Exit Sub
 
print_collection:
    For Each x In cl
        For i = x.Lbnd To x.Ubnd
            Debug.Print x(i),
        Next
        Debug.Print
    Next
Debug.Print
Return
End Sub
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.05.2012, 02:21
Помогаю со студенческими работами здесь

Для массива x(n) определить значение максимального эллемента массива и поменять его с первым элементом массива
Для массива x(n) определить значение максимального эллемента массива и поменять его с первым элементом массива

Автоматическое сопоставление свойства класса с элементом коллекции классов
Доброго времени суток. Сразу извиняюсь за корявое название темы. Сложно сформулировать кратко то, что хочу. Есть БД с которой...

Для каждого из заданных массивов определить второй отрицательный элемент массива и переставить его местами с первым по порядку элементом этого массива
Добрый день! помогите написать программы на VBA: №1. Заданы массивы А(40), В(20). С(30). Для каждого из заданных массивов определить...

Вычислить сумму между min элементом массива, и элементом, стоящим посередине
Нужно, чтобы программа вычисляла сумму между min элементом, и элементом, стоящим посередине Дан пример между min и max Помогите ...

Найти сумму элементов массива между максимальным элементом и центральным элементом
Sub massiv() Dim a(50) As Integer, m As Integer, s As Integer, c As Integer i = 2 Do Until Cells(i, 1) = "" a(i - 1) = Cells(i,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru