Страницы: 1
RSS
Поделитесь, у кого есть, кодом Fn VBA, которая принимает коллекцию как аргумент и возвращает все ее ключи, (именно ключи, не значения)
 
Привет! Поделитесь, у кого есть, кодом Fn VBA для 64 битного MS Excel, которая принимает коллекцию как аргумент и возвращает все ее ключи (именно ключи, не значения).
Изменено: Сергей Юрьевич - 12.01.2025 05:53:54
 
https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=161337&TITLE_SEO=161337-kak-uznat-key-tekushchego-item-pri-prosmotre-kollektsii&MID=1276315#message1276315

остальное сами.
По вопросам из тем форума, личку не читаю.
 
Код
Option Explicit
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 collItemOffset = 40
#Else
    Private Const ptrSz = 4
    Private Const varSz = 16
    Private Const collItemOffset = 24
#End If
Private Const NullPtr As LongPtr = 0

Function ColKeys(Coll As VBA.Collection) As String()
    Dim i&, pItem As LongPtr, Key$, pKey As LongPtr
    Dim Ub&: Ub = Coll.Count - 1
    If Ub = -1 Then Exit Function
    Dim Keys$(): ReDim Keys(Ub)
    pKey = VarPtr(Key)
    pItem = ObjPtr(Coll)
    For i = 0 To Ub
        CopyMemory pItem, ByVal pItem + collItemOffset, ptrSz
        CopyMemory ByVal pKey, ByVal pItem + varSz, ptrSz
        Keys(i) = Key
    Next
    CopyMemory ByVal pKey, NullPtr, ptrSz
    ColKeys = Keys
End Function

Private Sub ColKeysTest()
    Dim i&, Coll As New Collection
    Dim Keys$()
    
    Coll.Add "item1", "key1"
    Coll.Add "item2", "key2"
    Coll.Add "item3", "key3"

    Keys = ColKeys(Coll)
End Sub
Изменено: testuser - 12.01.2025 11:01:01
 
testuser, ну я на тот пост и указал :-)
Разве что тс не указал, что в итоге он хочет видеть, коллекцию ключей или массив ключей или массив ключ,значение...
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
Разве что тс не указал, что в итоге он хочет видеть, коллекцию ключей или массив ключей или массив ключ,значение...
А может уж и ни чего не надо, как это не редко бывает )
 
testuser, БМВ, спасибо огромное! То, что нужно!
Скажите, а в плане производительности это сопоставимо с Dictiory.keys()?
Без учета накладных на первоначальное создание самого объетка Dictiory или коллекции, ключи которого получаем.

Что скажете, подходит ли этот функционал для широкого использования, аналогично Dictiory.keys()?
Например. Задумал заменить в своем проекте все Dictionary на Коллекции. Мотивация - опасное поведение Dictionary при обращении к значению, он добавляет ключ, если его не было, даже тогда, когда я предпочел бы ошибку. Проект покрыт проверками Dictionary.Exists с функционалом выброса ошибки, если ключа нет, коллекция делала бы выброс ошибки по-умолчанию, что избавляет меня от нудных танцев с Dictionary и неочевидного Debugа.

Аналог .keys() для коллекций потребовался чтобы не городить дополнительный уровень вложености коллекции, хранящей Row таблицы (в отличии от Dictionary, Row в виде коллекции не может сообщить к каким столбцам она хранит значения из-за чего где-то в верхнеуровневом коде нужно выписывались названия столбцов или же хранить их в общей структуре DSetWithMeta с полями "rows", "columnNames". Т.е. образовался дополнительный уровень вложенности в сравнении с Dictionary).

Пример с Row не единственный, а лишь один частный случай, но очень часто Dictionary подкупает именно тем, что имеет метод .keys(), который в отличии от метода exists() сложно реализовать для коллекции (но благодаря вам, кажется, это теперь стало возможным).
Изменено: Сергей Юрьевич - 13.01.2025 02:19:55
 
Цитата
написал:
Разве что тс не указал, что в итоге он хочет видеть, коллекцию ключей или массив ключей или массив ключ,значение...
Да это не имеет принципиального значения) Я нуждался в низкоуровневом образце кода с трюком, проверенным практикой, а потому устойчивый к ошибкам, чтобы утащить к себе в проект и видоизменить. Теперь, когда я получил такие образцы благодаря вам, мои мысли оставили это и меня интересует вопрос цены в плане производительности в сравнении с тем же Dictionary.
Изменено: Сергей Юрьевич - 13.01.2025 02:34:55
 
Цитата
Сергей Юрьевич написал:
опрос цены в плане производительности в сравнении с тем же Dictionary.
Как правило, хватает обычного Dictionary. Все зависит, конечно от задачи, но имхо лучше в алгоритме избегать такого сюжета, когда многократно получается массив ключей или значений, а реализовать это как-то по другому.
Изменено: testuser - 13.01.2025 07:09:53
 
testuser, это понятно, что выгрузку ключей лучше переиспользовать. Вопрос был другой - эффективность ColKeys, пример которой вы привели, в плане производительности. Сильно уступает методу keys(), который у Dictionary (при равном наборе ключей и значений)? Или призводительность сопоставима и переписав проект, избавив его от Dictionary, я не получу жесткой просадки производительности в части .keys() функционала? Вы не тестировали ее в плане перформанса?
Изменено: Сергей Юрьевич - 13.01.2025 07:51:27
 
В моей не очень обильной истории макрописца только однажды коллекция окащалась быстрее, но
Коллекция более универсальна при использовании на pc и Mac
Позволяет сортировать
Пробигало мнение что после 100 000 словарь начинает притормаживать в отличии ит коллекции.

Иными словами, лишние строки кода могут быть компенсированы скоростью, но все зависит от потребеости.
По вопросам из тем форума, личку не читаю.
 
Цитата
Сергей Юрьевич написал:
Или призводительность сопоставима и переписав проект, избавив его от Dictionary, я не получу жесткой просадки производительности в части .keys() функционала? Вы не тестировали ее в плане перформанса?
Конкретно этот момент я не тестировал. Самописная функция выполняемая на vba, компилируемом в режиме p-code, вероятнее всего будет медленей функции из нативно-скомпилированной библиотеки. Плю на x64 vba добавляются жесткие тормоза на вызов Api-функций. Другой вопрос, на сколько это будет медленей, заметно ли это для глазу в каком-то конкретном случае, вы конечно можете это протестировать и т.о. внести какую-то ясность в этом моменте.
Цитата
БМВ написал:
Пробигало мнение что после 100 000 словарь
Я однажды экспериментировал с изобретением самописного словаря и заодно сравнил скорость заполнения + поиска в коллекции и словаре случайных строковых ключей. И у меня почему-то коллекции оказывалась сильно быстрей даже на куда меньшем количестве, т.е. 10к очень было заметно. Главное, я думаю учитывать разную реализацию поиска у коллекции - бинарное дерево, от словаря - хеш-таблица. Бинарное дерево лучше заполнять случайными данными, или если данные отсортированы, то заполнять их в случайном порядке. Для хэш-таблицы это не критично, но у нее (конкретно у Dictionary) есть другой недостаток - сама хэш-таблица внутри словаря имеет четко фиксированый размер, это понятно по тому факту, что после определенного колличества ключей, начинает заметно падать скорость поиска.
 
Добрый день, я немного выпал из форума, может что пропустил. Куда у нас пропал, самый большой любитель замера скорости и экономии миллисекунд Jack Famous?
 
Цитата
написал:
И у меня почему-то коллекции оказывалась сильно быстрей даже на куда меньшем количестве, т.е. 10к очень было заметно
Если вы создали словарь так:
Код
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")

То это долгий старт для Dictionary и тогда понятно почему вам приходится говорить о разительной разнице.
Для себя решил отказаться от такого способа создания словарей.
Изменено: Сергей Юрьевич - 13.01.2025 12:55:07
 
Цитата
написал:
Коллекция более универсальна при использовании на pc и MacПозволяет сортировать
В смысле коллекция позволяет сортировать? Вы имеете в виду хранит порядок в котором элементы были добавлены? Dictionary тоже порядок внесения запоминает.
Изменено: Сергей Юрьевич - 13.01.2025 15:18:31
 
Сергей Юрьевич, нет. Я имею в виду что можно провести сортировку в коллекции. Изменив порядок. Как и в массиве.
По вопросам из тем форума, личку не читаю.
 
Словарь тоже можно сортировать при желании https://www.cyberforum.ru/visual-basic/thread1146688-page2.html#post6044230
Я сам не пробовал )
 
Цитата
testuser написал:
Я сам не пробовал )
а желание глядя на код было??? ;-)
Цитата
Msi2102 написал:
Куда у нас пропал, самый большой любитель замера скорости и экономии миллисекунд Jack Famous?
Ушел в кибирпространство
По вопросам из тем форума, личку не читаю.
 
Короче может это уже было но пусть будте. Действительно что-то там после 100000
Скрытый текст
Изменено: testuser - 13.01.2025 16:59:15
 
БМВ,
Цитата
написал:
Сергей Юрьевич , нет. Я имею в виду что можно провести сортировку в коллекции. Изменив порядок. Как и в массиве.
Как же вы измените порядок?  Если вы попытаетесь перезаписать значение, то получите ошибку.
Код
Dim MyCol As New Collection  
MyCol.Add "Апельсины", "ключ1"
MyCol.Item("ключ1") = "Бананы" ' Ошибка

А если вы будете удалять и добавлять элемент заново и таким образом добиваться сортировки (типо сортировки пузырьком, но снизу), то тоже самое можно делать и в Dictionary.

Изменено: Сергей Юрьевич - 14.01.2025 15:13:40
 
Цитата
Сергей Юрьевич написал:
Как же вы измените порядок?
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/add-method-visua...
before Optional. An expression that specifies a relative position in the collection. The member to be added is placed in the collection before the member identified by the before argument. If a numeric expression, before must be a number from 1 to the value of the collection's Count property. If a string expression, before must correspond to the key specified when the member being referred to was added to the collection. You can specify a before position or an after position, but not both.

after Optional. An expression that specifies a relative position in the collection. The member to be added is placed in the collection after the member identified by the after argument. If numeric, after must be a number from 1 to the value of the collection's Count property. If a string, after must correspond to the key specified when the member referred to was added to the collection. You can specify a before position or an after position, but not both.

Есть такое у словаря?
Изменено: БМВ - 14.01.2025 20:08:37
По вопросам из тем форума, личку не читаю.
Страницы: 1
Наверх