Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.72/92: Рейтинг темы: голосов - 92, средняя оценка - 4.72
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19

Как получить название ключа в коллекции

14.02.2014, 19:59. Показов 18605. Ответов 65
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Делаю свой класс
который бы, имитировал класс Scripting.Dictionary
остановился на функции возврата списка имен ключей
где я тут чего не доглядел, где что упустил ?


Модуль класса
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
39
Option Explicit
 
Private CL As Collection
Function Keys()
'Вот тут я остановился
'    Dim f&, v, v1
'    ReDim v(CL.Count - 1)
'    For Each v1 In CL
'        v(f) = CL(f + 1)
'        f = f + 1
'    Next
End Function
 
Public Sub Add(Key$, Item)
    CL.Add Item, Key
End Sub
 
Function Exists(Key) As Boolean
    On Error Resume Next
    Call CL.Item(Key)
    If Err.Number Then Else Exists = True
End Function
 
Function Items() As Variant()
    Dim f&, v, v1
    ReDim v(CL.Count - 1)
    For Each v1 In CL
        v(f) = v1
        f = f + 1
    Next
End Function
 
Private Sub Class_Initialize()
    Set CL = New Collection
End Sub
 
Private Sub Class_Terminate()
    Set CL = Nothing
End Sub
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.02.2014, 19:59
Ответы с готовыми решениями:

Как изменить имя ключа в коллекции?
Есть коллекция Dictionary<String, Process> PrcDic; (Process - самодельный класс). А как изменить значение одного из ключей...

Как узнать название лейбла элемента коллекции по номеру
Добрый день. Есть задача: После считывания меню создается коллекция вида: collection_menu.Add parameters, Name_Fuction ...

Использование коллекции с идентификатором ключа в виде пользовательского типа
Здравствуйте уважаемые форумчане. Очень неудобно обращаться к вам с такой просьбой, но на данный момент у меня нет другого выхода. Учу...

65
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 01:09  [ТС]
Студворк — интернет-сервис помощи студентам
Я уже догадываюсь как это обойти
для этого ключ нужно записывать в юникоде, а это пара на каждый символ

Добавлено через 4 минуты
а возвращать в обычном Ansi из расшифрованного юникода
всё это уже не столь принципиально
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
16.02.2014, 01:10
Цитата Сообщение от FelixMacintosh Посмотреть сообщение
Я уже догадываюсь как это обойти
для этого ключ нужно записывать в юникоде, а это пара на каждый символ
Нет, ты неверно догадываешься. Ключи коллекции хранятся уже в юникоде (например символы кириллицы уже занимают по 2 байта полностью), а внутренняя реализация коллекции не даст добавиться одинаковым ключам (TextCompare). Правильно написать с нуля класс коллекция, где дать возможность выбора режима сравнения.
0
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 01:10  [ТС]
в юникоде, тоесть к каждому символу дописать регистр
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
16.02.2014, 01:14
Цитата Сообщение от FelixMacintosh Посмотреть сообщение
в юникоде, тоесть к каждому символу дописать регистр
Мммм... Что значит дописать? Расширить в 2 раза ключ? "The Trick" - "uTlhle uTlrlilclk"?
0
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 01:17  [ТС]
Например: аБв = а0б1в0

Добавлено через 2 минуты
Ну реализовать можно по другому 010 записать както компактнее )
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
16.02.2014, 01:18
Цитата Сообщение от FelixMacintosh Посмотреть сообщение
Например: аБв = а0б1в1
Ну это неважно будь Unicode или Ansi, будет дополнительно уходить время на распарсивание ключа. Напиши сразу хеш функцию и с помощью нее получай доступ к элементам, реализуй разрешение коллизий и все.
0
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 04:15  [ТС]
Добавлено через 1 минуту
Цитата Сообщение от The trick Посмотреть сообщение
реализуй разрешение коллизий
чет не разу с таким термином не сталкивался )
да и не столкнулся бы если бы не это обсуждение )))

Я в своём мененжере API функций не нашол как декларируются
некоторые из тех что выложил The trick
Нашел здесь об указателях
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
16.02.2014, 05:00
Лучший ответ Сообщение было отмечено The trick как решение

Решение

Цитата Сообщение от FelixMacintosh Посмотреть сообщение
вы говорите о дополнительном времени уточню для новых участников 1/100000... секунд
разьве это принципиально, и стоит ли, ради этой доли секунды, делать отдельно, целый класс коллекции
.. думаю нет, .. как еще говорят тут на слэнге .. танцы с бубном ...
Тебе быстрее и проще будет написать свою реализацию Dictonary, в этом ничего особенного нет. Вот пример я сделал небольшое подобие функционала Dictonary
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
Option Explicit
 
Private Type tPointer
    Hash As Integer
    Index As Integer
End Type
Private Type tElement
    Key As String
    Value As String
    Next As tPointer
    Prev As tPointer
End Type
Private Type tItem
    ElementsCount As Long
    Elements() As tElement
End Type
 
Private Dat() As tItem
Private mCount As Long
Private mCompareMethod As VbCompareMethod
Private First As tPointer, Last As tPointer
 
Public Property Get CompareMethod() As VbCompareMethod
    CompareMethod = mCompareMethod
End Property
Public Property Let CompareMethod(ByVal Value As VbCompareMethod)
    If mCount Then Err.Raise 5: Exit Property    ' Òîëüêî êîãäà ýëåìåíòîâ íåò
    mCompareMethod = Value
End Property
Public Sub Add(Key As String, Value As String)
    Dim pt As tPointer
    pt = GetFromKey(Key)
    If pt.Index <> -1 Then Err.Raise 457: Exit Sub
    pt.Index = Dat(pt.Hash).ElementsCount
    ReDim Preserve Dat(pt.Hash).Elements(pt.Index)
    Dat(pt.Hash).ElementsCount = pt.Index + 1
    Dat(pt.Hash).Elements(pt.Index).Value = Value
    Dat(pt.Hash).Elements(pt.Index).Key = Key
    
    If Last.Hash >= 0 Then
        Dat(Last.Hash).Elements(Last.Index).Next = pt
        Dat(pt.Hash).Elements(pt.Index).Prev = Last
    Else
        Dat(pt.Hash).Elements(pt.Index).Prev.Hash = -1
        Dat(pt.Hash).Elements(pt.Index).Prev.Index = -1
        First = pt
    End If
    Dat(pt.Hash).Elements(pt.Index).Next.Hash = -1
    Dat(pt.Hash).Elements(pt.Index).Next.Index = -1
    Last = pt
    mCount = mCount + 1
End Sub
Public Property Get Item(Key As String) As String
    Dim pt As tPointer
    pt = GetFromKey(Key): If pt.Index = -1 Then Err.Raise 5: Exit Property
    Item = Dat(pt.Hash).Elements(pt.Index).Value
End Property
Public Property Let Item(Key As String, Value As String)
    Dim pt As tPointer
    pt = GetFromKey(Key): If pt.Index = -1 Then Err.Raise 5: Exit Property
    Dat(pt.Hash).Elements(pt.Index).Value = Value
End Property
Public Property Get Count() As Long
    Count = mCount
End Property
Public Function Exist(Key As String) As Boolean
    Exist = GetFromKey(Key).Index <> -1
End Function
Public Sub Remove(Key As String)
    Dim pt As tPointer, l As Long, ln As tPointer, lp As tPointer, p As tPointer
    pt = GetFromKey(Key): If pt.Index = -1 Then Err.Raise 5: Exit Sub
    lp = Dat(pt.Hash).Elements(pt.Index).Prev: ln = Dat(pt.Hash).Elements(pt.Index).Next
    For l = pt.Index To Dat(pt.Hash).ElementsCount - 2
        Dat(pt.Hash).Elements(l) = Dat(pt.Hash).Elements(l + 1)
        ' Ïðàâèì ññûëêè íà ýëåìåíò
        p = Dat(pt.Hash).Elements(l).Prev
        If p.Index >= 0 Then Dat(p.Hash).Elements(p.Index).Next.Index = Dat(p.Hash).Elements(p.Index).Next.Index - 1
        p = Dat(pt.Hash).Elements(l).Next
        If p.Index >= 0 Then Dat(p.Hash).Elements(p.Index).Prev.Index = Dat(p.Hash).Elements(p.Index).Prev.Index - 1
    Next
    l = Dat(pt.Hash).ElementsCount - 1: Dat(pt.Hash).ElementsCount = l
    If l Then
        ReDim Preserve Dat(pt.Hash).Elements(l - 1)
    Else
        Erase Dat(pt.Hash).Elements()
    End If
    ' Ïðàâèì ññûëêè
    If lp.Index >= 0 Then Dat(lp.Hash).Elements(lp.Index).Next = ln
    If ln.Index >= 0 Then Dat(ln.Hash).Elements(ln.Index).Prev = lp
    If lp.Index = -1 Then First = ln
    If ln.Index = -1 Then Last = lp
    mCount = mCount - 1
End Sub
Public Sub Clear()
    Call Class_Initialize
End Sub
Public Function HashValue(S As String) As Long
    Dim i As Long, ch As Integer
    For i = 0 To Len(S) - 1
        HashValue = (HashValue * 11 + AscW(LCase(Mid$(S, i + 1, 1)))) And &HFFFF&
    Next
    HashValue = HashValue Mod 999
End Function
Public Function Items() As String()
    Dim pt As tPointer, i As Long, ret() As String
    If mCount = 0 Then Exit Function
    pt = First: ReDim ret(mCount - 1)
    Do
        ret(i) = Dat(pt.Hash).Elements(pt.Index).Value
        pt = Dat(pt.Hash).Elements(pt.Index).Next
        i = i + 1
    Loop While i < mCount
    Items = ret
End Function
Public Function Keys() As String()
    Dim pt As tPointer, i As Long, ret() As String
    If mCount = 0 Then Exit Function
    pt = First: ReDim ret(mCount - 1)
    Do
        ret(i) = Dat(pt.Hash).Elements(pt.Index).Key
        pt = Dat(pt.Hash).Elements(pt.Index).Next
        i = i + 1
    Loop While i < mCount
    Keys = ret
End Function
Private Function GetFromKey(K As String) As tPointer
    Dim i As Long, h As Long
    h = HashValue(K): GetFromKey.Hash = h
    For i = 0 To Dat(h).ElementsCount - 1
        If StrComp(Dat(h).Elements(i).Key, K, mCompareMethod) = 0 Then GetFromKey.Index = i: Exit Function
    Next
    GetFromKey.Index = -1
End Function
Private Sub Class_Initialize()
    ReDim Dat(998): First.Hash = -1: First.Index = -1: Last.Hash = -1: Last.Index = -1
End Sub
Private Sub Class_Terminate()
    Erase Dat()
End Sub
Добавить IEnumVariant и можно будет использовать в циклах For Each.
6
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 05:20  [ТС]
Вы просто молодец ! +5 вам за это

а я несколько часов просидел чтоб добиться функционала, правда более приметивнее
получилось чем у вас ... вот часть кода ...

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Public Property Let Key(ByVal Key$, ByVal vNewValue As String)
    Dim v, v1, v2, f&
    v = c1(Key)
    v1 = Keys: v2 = Items
    Set c1 = Nothing: Set c1 = New Collection
    For f = 0 To UBound(v1)
        If StrComp(v1(f), Key, 1) = 0 Then
            c1.Add v2(f), vNewValue
        Else
            c1.Add v2(f), v1(f)
        End If
    Next
End Property
Тоесть там переименование ключа, и перезапись всей колекции чтоб порядок таким-же был )))
я даже не стану весь код показывать чтоб не позорится

вначале я вообще делал так ...

Visual Basic
1
2
3
4
    Dim v
    v = c1(Key)
    c1.Remove (Key)
    c1.Add v, vNewValue
0
15155 / 6428 / 1731
Регистрация: 24.09.2011
Сообщений: 9,999
16.02.2014, 14:23
Таак, программа прогрессирует!
Надо не забыть, что словарь и коллекция могут хранить ссылки на объекты. Чтобы это учесть, самый первый вариант следует модифицировать так:
Visual Basic
1
2
3
Public Property Get Item(Key) As Variant
    If IsObject(c1(Key)) Then Set Item = c1(Key) Else Item = c1(Key)
End Property
Также модифицировать Property Let и добавить Property Set.
0
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
16.02.2014, 17:34  [ТС]
Цитата Сообщение от Казанский Посмотреть сообщение
Public Property Get Item(Key) As Variant
Кстате да, у себя я реализовал так, чтоб вариант возвращал

интересно почему The trick написал String
...вот его 53-я строчка Public Property Get Item(Key As String) As String
одно скажу, The trick просто так ничего не пишет
его трудно в чем-то упрекнуть, (я однажды пытался, и чуть не надоровался )

Добавлено через 4 минуты
Одно знаю, что String работает побыстрее чем Variant возможно
он учитывает, то , для чего, я пытаюсь делать свой класс словаря (Dictionary)
1
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
16.02.2014, 17:35
Цитата Сообщение от FelixMacintosh Посмотреть сообщение
интересно почему The trick написал String
подобие функционала Dictonary
Это был просто пример, я вообще стараюсь с вариантами не работать по-возможности. К тому же пришлось бы кучу дополнительных проверок делать типа IsObject() и т.п., т.к. это пример и его еще надо допиливать хотя бы чтобы поддерживал For Each, я не стал заморачиваться.
1
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
18.02.2014, 19:27
Лучший ответ Сообщение было отмечено The trick как решение

Решение

Наконец доделал код реализующий поддержку For Each циклов по коллекции.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Option Explicit
 
Private Sub Form_Load()
    Dim Col As clsMyCollection, Itm As Variant
 
    Set Col = New clsMyCollection
    ' Перечисление
    For Each Itm In Col
        Debug.Print Itm
    Next
End Sub
Изображения
 
3
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
18.02.2014, 19:49  [ТС]
С твоими мозгами нужно работать в Гугле!

..И хорошая идея с Gif

Добавлено через 11 минут

Не по теме:

Админы поставте ему 100 балов !

1
1385 / 840 / 91
Регистрация: 08.02.2017
Сообщений: 3,569
Записей в блоге: 1
22.11.2023, 15:28
Цитата Сообщение от The trick Посмотреть сообщение
Ключи можно получить непосредственно из коллекции
Сделал реплику под vba
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
Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#If Win64 Then
    Private Const ptrSz = 8
    Private Const varSz = 24
    Private Const collPtrOffset = 40
#Else
    Private Const ptrSz = 4
    Private Const varSz = 16
    Private Const collPtrOffset = 24
#End If
Private Function CollKey(ByVal Index As Long, Coll As Collection) As String
    Dim i As Long, Ptr0 As LongPtr, Ptr As LongPtr, Key As String
    If Coll Is Nothing Then Exit Function
    Select Case Index
    Case Is < 1, Is > Coll.Count: Exit Function
    Case Else
        Ptr = ObjPtr(Coll)
        For i = 1 To Index
            CopyMemory Ptr, ByVal Ptr + collPtrOffset, ptrSz
        Next
        CopyMemory ByVal VarPtr(Key), ByVal Ptr + varSz, ptrSz
        CollKey = Key
        CopyMemory ByVal VarPtr(Key), Ptr0, ptrSz
    End Select
End Function
Вариант2
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
Private Type tpCollElem
    item As Variant
    Key As String
    prvPtr As LongPtr
    nxtPtr As LongPtr
End Type
 
Private Function CollKey2(ByVal Index As Long, Coll As Collection) As String
    Dim collElem As tpCollElem
    CollKey2_ Index, Coll, CollKey2, collElem
End Function
Private Sub CollKey2_(ByVal Index As Long, Coll As Collection, Key As String, collElem As tpCollElem, _
                      Optional Ptr As LongPtr, Optional pPtr As LongPtr)
    Dim i As Long, lpTmp As LongPtr
    If Coll Is Nothing Then Exit Sub
    Select Case Index
    Case Is < 1, Is > Coll.Count: Exit Sub
    Case Else
        CopyMemory ByVal VarPtr(Index) + ptrSz * 5, VarPtr(Index) + ptrSz * 4, ptrSz
        pPtr = ObjPtr(Coll) + collPtrOffset: lpTmp = Ptr
        pPtr = VarPtr(Index) + ptrSz * 3: Ptr = lpTmp
        For i = 2 To Index
            Ptr = collElem.nxtPtr
        Next
        Key = collElem.Key
    End Select
End Sub
Добавлено через 12 минут
Блин, только сейчас заметил во втором варианте index то Byval, "заглушку" можно было не ставить в конце, а вычислять указатели от индекса.

Добавлено через 15 минут
исправил
2
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
22.11.2023, 16:21
testuser2, Отлично получилось!
Только вот зачем всё это, если есть словари
0
1385 / 840 / 91
Регистрация: 08.02.2017
Сообщений: 3,569
Записей в блоге: 1
22.11.2023, 17:15
Jack Famous, даже не знаю, я тоже люблю пользоваться словарями, но в даннм случае видно, что есть прямой доступ к ключам и значениям коллекции, если бы такое можно было осуществить со словарем, это было бы круто, но, похоже, там сложее все устроено. Это расширяет возможности коллекции конечно, можно, допустим, не затратно по времени (как я думаю), получить массив ключей, копируя, их указатели в строковый массив.. Также массив значений коллекции..
1
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
22.11.2023, 18:21
Цитата Сообщение от testuser2 Посмотреть сообщение
если бы такое можно было осуществить со словарем
Сортировка словаря методом реконструкции
2
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.11.2023, 19:50
Заодно Класс CollectionEx
2
1385 / 840 / 91
Регистрация: 08.02.2017
Сообщений: 3,569
Записей в блоге: 1
24.11.2023, 02:41
Короче наизобретал тут.. Получение указательных массивов на ключи и итемы коллекции (под VBA).
Кликните здесь для просмотра всего текста
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Option Explicit
Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Private Declare PtrSafe Function ArrPtr Lib "VBE7" Alias "VarPtr" (Arr() As Any) As LongPtr
 
Private Type pVariant
    cur As Currency
    Ptr As LongPtr
    lp0 As LongPtr
End Type
Private Type tpCollElemPtr
    pItem As pVariant
    pKey As LongPtr
    prvPtr As LongPtr
    nxtPtr As LongPtr
End Type
Private Type sArray
    sArr() As String
End Type
 
#If Win64 Then
    Private Const ptrSz = 8
    Private Const varSz = 24
    Private Const collPtrOffset = 40
#Else
    Private Const ptrSz = 4
    Private Const varSz = 16
    Private Const collPtrOffset = 24
#End If
 
'Получение массива строк-указателей ключей коллекции
Private Sub CollKeys(Coll As Collection, Keys As sArray, pKeys() As LongPtr)
    Dim collElem As tpCollElemPtr
    CollKeys_ Coll, Keys, pKeys, collElem
End Sub
Private Sub CollKeys_(Coll As Collection, Keys As sArray, pKeys() As LongPtr, collElem As tpCollElemPtr, _
                      Optional Ptr As LongPtr, Optional pPtr As LongPtr, Optional ByVal Ptr0 As LongPtr)
    Dim i As Long, Cnt As Long, lpTmp As LongPtr, ptKeys As LongPtr
    
    If Coll Is Nothing Then Exit Sub
    Cnt = Coll.Count
    If Cnt Then
        ReDim Keys.sArr(1 To Cnt, 1 To 1)
        CopyMemory ByVal VarPtr(Ptr0) - ptrSz, VarPtr(Ptr0) - ptrSz * 2, ptrSz
        pPtr = VarPtr(Keys): lpTmp = Ptr
        pPtr = ArrPtr(pKeys): Ptr = lpTmp
        pPtr = ObjPtr(Coll) + collPtrOffset: lpTmp = Ptr
        pPtr = VarPtr(Ptr0) - ptrSz * 3: Ptr = lpTmp
        
        pKeys(1, 1) = collElem.pKey
        For i = 2 To Cnt
            Ptr = collElem.nxtPtr
            pKeys(i, 1) = collElem.pKey
        Next
    End If
End Sub
'Получение массива значений/указателей коллекции
Private Sub CollItems(Coll As Collection, Items() As Variant, pItems() As pVariant)
    Dim collElem As tpCollElemPtr
    CollItems_ Coll, Items, pItems, collElem
End Sub
Private Sub CollItems_(Coll As Collection, Items() As Variant, pItems() As pVariant, collElem As tpCollElemPtr, _
                      Optional Ptr As LongPtr, Optional pPtr As LongPtr, Optional ByVal Ptr0 As LongPtr)
    Dim i As Long, Cnt As Long, lpTmp As LongPtr, ptItems As LongPtr
    
    If Coll Is Nothing Then Exit Sub
    Cnt = Coll.Count
    If Cnt Then
        ReDim Items(1 To Cnt, 1 To 1)
        CopyMemory ByVal VarPtr(Ptr0) - ptrSz, VarPtr(Ptr0) - ptrSz * 2, ptrSz
        pPtr = ArrPtr(Items): lpTmp = Ptr
        pPtr = ArrPtr(pItems): Ptr = lpTmp
        pPtr = ObjPtr(Coll) + collPtrOffset: lpTmp = Ptr
        pPtr = VarPtr(Ptr0) - ptrSz * 3: Ptr = lpTmp
        
        pItems(1, 1) = collElem.pItem
        For i = 2 To Cnt
            Ptr = collElem.nxtPtr
            pItems(i, 1) = collElem.pItem
        Next
    End If
End Sub

Пример использования
Кликните здесь для просмотра всего текста
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
Private Sub Пример()
    Dim Coll As New Collection
    Dim Keys As sArray, pKeys() As LongPtr
    Dim Items() As Variant, pItems() As pVariant, pVEmp As pVariant
    Dim i&, Ctn&, Ptr0 As LongPtr
    
    Coll.Add "item1", "key1"
    Coll.Add "item2", "key2"
    Coll.Add "item3", "key3"
    Cnt = Coll.Count
    
    CollKeys Coll, Keys, pKeys
    CollItems Coll, Items, pItems
    
    Range("A1").Resize(Cnt).Value = Keys.sArr
    Range("B1").Resize(Cnt).Value = Items
    
    'освобождение указателей
    For i = 1 To Cnt
        pKeys(i, 1) = 0
    Next
    CopyMemory ByVal ArrPtr(pKeys), Ptr0, ptrSz
    For i = 1 To Cnt
        pItems(i, 1) = pVEmp
    Next
    CopyMemory ByVal ArrPtr(pItems), Ptr0, ptrSz
End Sub


Добавлено через 5 минут
Фактически если в вариантном массиве значений не будет ссылок (ссылочных типов), то массив указателей не нужен и можно его "упразднить" для такого случая
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.11.2023, 02:41
Помогаю со студенческими работами здесь

Как получить список вместо коллекции
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using...

Как в Ajax получить значение определенного ключа?
сейчас мне Ajax возвращает результат вот в таком виде {&quot;org&quot;:&quot;IK1&quot;,&quot;con&quot;:null,&quot;reg_date&quot;:&quot;2016-06-10...

Как получить все значения по полю в коллекции?
Например есть коллекция Книги в ней если по индексу обращаться Books.Author то можно взять значения автора каждого, как еще можно через...

Как правильно получить последний элемент коллекции?
Доброго времени суток! Возникла пролема с использованием метода .ElementAt(). Необходимо получить последний элемент коллекции для...

Как получить тип элемента обобщенной коллекции?
Добрый день, господа! Столкнулся с нетривиальной задачей: как получить тип элемента коллекции List&lt;T&gt;, в которой нет значений. ...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru