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

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

14.02.2014, 19:59. Показов 19520. Ответов 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
933 / 366 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
24.11.2023, 09:26
Студворк — интернет-сервис помощи студентам
testuser2, нужны тесты времени работы в сравнении со словарём (до 50 тыс ключей).
Если сделаете, с удовольствием посмотрю.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 12:59
Jack Famous, тут больше не для скорости а для души ) Я конечно минимизировал вызовы CopyMemory (оставив один на процедуру), но, если ориентироваться на скорость, лучше вообще убрать CopyMemory из процедуры. Трик уже сказал, что на vba x64 при вызове любой Api-функции, происходит куча дополнитлеьных действий. Т.е., видимо, если что-то делается очень часто, лучше убрать там любые WinApi. Вот, кстати, кое что в этом направлении выяснилось. Можно ArrPtr выкинуть (если он конечно где-то что-то замедляет).. Для начала новый вариант функции CollKeys, где новый способ получения указателя массива.
Кликните здесь для просмотра всего текста
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
Private Sub CollKeys2(Coll As Collection, Keys() As String, pKeys() As LongPtr)
    Dim collElem As tpCollElemPtr
    CollKeys2_ Coll, Keys, pKeys, collElem
End Sub
Private Sub CollKeys2_(Coll As Collection, Keys() As String, 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(1 To Cnt, 1 To 1)
        CopyMemory ByVal VarPtr(Ptr0) - ptrSz, VarPtr(Ptr0) - ptrSz * 2, ptrSz
        Ptr0 = VarPtr(Ptr0)
        pPtr = Ptr0 - ptrSz * 5: pPtr = Ptr: lpTmp = Ptr 'получение указателя Keys()
        pPtr = Ptr0 - ptrSz * 4: pPtr = Ptr: Ptr = lpTmp '2й вариант: pPtr = ArrPtr(pKeys): Ptr = lpTmp
        pPtr = ObjPtr(Coll) + collPtrOffset: lpTmp = Ptr
        pPtr = 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 Пример()    
    Dim Coll As New Collection
    Dim Ptr0 As LongPtr, pKeys() As LongPtr, Keys() As String
    Dim i&, Cnt&
    
    Coll.Add "item1", "key1"
    Coll.Add "item2", "key2"
    Coll.Add "item3", "key3"
    Cnt = Coll.Count
    
    CollKeys2 Coll, Keys, pKeys
    
    Range("A1").Resize(Cnt).Value = Keys 
    
    'освобождение указателей
    For i = 1 To Cnt
        pKeys(i, 1) = 0
    Next
    CopyMemory ByVal VarPtr(Ptr0) - ptrSz, Ptr0, ptrSz 'CopyMemory ByVal ArrPtr(pKeys), Ptr0, ptrSz
End Sub

В VB/VBA есть баг с получением указателя на строковый массив - api-функция ArrPtr возвращает 0 вместо указателя на массив. В предыдущей версии процедуры я использовал udt с массивом внутри, для получения указателя. Но на самом деле есть и другие варианты, как в данном случае - вычисления указателя в стеке аргументов (строки 15, 16). Но если массив задекларирован как обычная переменная, то получить указатель на массив, как оказалось, еще проще.
Visual Basic
1
2
3
Dim lp as longPtr, sArr() As String
lp = VarPtr(lp) - len(lp)
Debug.Ptring "Указатель массива: "; lp
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 13:03
Цитата Сообщение от testuser2 Посмотреть сообщение
lp = VarPtr(lp) - len(lp)
Не понимаю, почему работает этот код, я бы делал VarPtr(lp) + 4 ну или + 8, если longPtr это 8 байт, я просто не знаю ваших VBA'шных штучек этих

Добавлено через 29 секунд
А может я в этом и не разбираюсь просто...
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 13:08
HackerVlad, LongPtr это автоматический тип, который в 32 битах является Long (4 байт), в x64 LongLong(8 байт) очень удобная вещь, не надо писать дополнительных проверок и директив прекомпиляции (#IF Win64 Then), он автоматически подстраивается под ситуацию
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 13:25
testuser2, спасибо за объяснение, но всё равно я не понимаю почему там у тебя минус, а не плюс в коде

Добавлено через 28 секунд
Логичнее было бы lp = VarPtr(lp) + len(lp) тогда...
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 13:30
Цитата Сообщение от HackerVlad Посмотреть сообщение
я не понимаю почему там у тебя минус
а самому проверить в лом? )
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 13:30
testuser2, и кстати я никогда не пользуюсь ArrPtr или этими приблудами, я просто всегда пользуюсь кодом VarPtr(sArr(0)) вот и весь код получения указателя на массив, главное чтобы он был инициализирован
0
933 / 366 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
24.11.2023, 13:31
Цитата Сообщение от testuser2 Посмотреть сообщение
если что-то делается очень часто, лучше убрать там любые WinApi
не могу согласиться.
Возможно, некоторые апи и медленнее работают на x64, но все ли? К тому же, медленнее, чем на x32 всё равно может быть заметно быстрее, чем прочие НЕапи-аналоги. У меня немало на апи и это самые быстрые решения из найденных.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 13:35
testuser2, как ты не понимаешь, я же не VBA'шник, у меня нет VBA чтобы проверить это

Добавлено через 2 минуты
Цитата Сообщение от testuser2 Посмотреть сообщение
а самому проверить в лом? )
А объяснить тебе влом? Например такое могло бы быть возможно в CDecl...

Добавлено через 44 секунды
Не, я не понимаю почему минус, а не плюс

Добавлено через 57 секунд
Цитата Сообщение от Jack Famous Посмотреть сообщение
но все ли
Вроде трик говорил что вызов любой АПи медленный
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 13:44
Цитата Сообщение от HackerVlad Посмотреть сообщение
у меня нет VBA чтобы проверить это
Забыл сделать пояснение для своего примера. Для VB нужно просто все longPtr заменить на Long, константу ptrSz на 4&

Добавлено через 1 минуту
Visual Basic
1
2
3
Dim lp as long, sArr() As String
lp = VarPtr(lp) - 4
Debug.Ptring "Указатель массива: "; lp
Добавлено через 4 минуты
Цитата Сообщение от HackerVlad Посмотреть сообщение
я просто всегда пользуюсь кодом VarPtr(sArr(0)) вот и весь код получения указателя на массив
Это указатель на данные массива, а ArrPtr дает указатель на заголовок массива, точнее указатель на указатель заголовочной структуры SafeArray
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 13:48
testuser2, всё равно мне непонятно почему минус а не плюс

Добавлено через 1 минуту
Уверен, что в Vb6 нужно получать указатель на массив так:

Visual Basic
1
2
3
Dim lp as long, sArr() As String
lp = VarPtr(lp) + 4
Debug.Ptring "Указатель на массив: "; lp
0
24.11.2023, 13:55

Не по теме:

Цитата Сообщение от HackerVlad Посмотреть сообщение
Например такое могло бы быть возможно в CDecl...
На VB можно написать функцию CDecl? Впрочем все это флуд, тема про коллекции.

0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 14:01
testuser2, я не вижу от тебя ни одной объяснения: почему минус, а не плюс? сто раз уже спросил

Добавлено через 16 секунд
мне вот непонятно это совсем

Добавлено через 1 минуту
Цитата Сообщение от testuser2 Посмотреть сообщение
На VB можно написать функцию CDecl?
Конечно можно, перекладывай стек вручную или используй надстройку The Trick но то что можно это 100%

Добавлено через 46 секунд
testuser2, да и мы с тобой уже обсуждали CDecl функции в одной из моих тем, как ты мог забыть
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.11.2023, 14:02
Цитата Сообщение от testuser2 Посмотреть сообщение
Для VB нужно просто все longPtr заменить на Long
Можно сделать так:
Visual Basic
1
2
3
Public Enum LongPtr
[_]
End Enum
1
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 15:06

Не по теме:

Цитата Сообщение от HackerVlad Посмотреть сообщение
Конечно можно, перекладывай стек вручную или используй надстройку The Trick но то что можно это 100%
Если такой умный, почему спрашиваешь глупые вещи?



Добавлено через 55 минут
Цитата Сообщение от HackerVlad Посмотреть сообщение
я не вижу от тебя ни одной объяснения: почему минус, а не плюс?
Потому что я проверил - так работает. Если у кого-то не работает он может опровергнуть "закон мерфи"
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 16:41
testuser2, а плюс не работает?
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
24.11.2023, 17:00
Deleted
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.11.2023, 17:15
Цитата Сообщение от testuser2 Посмотреть сообщение
Deleted
очень умно) ахаххаах
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
26.11.2023, 07:26
Цитата Сообщение от HackerVlad Посмотреть сообщение
плюс не работает?
работает
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
26.11.2023, 08:32
testuser2, тогда почему минус а не плюс?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.11.2023, 08:32

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Сезонность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru