Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.93/57: Рейтинг темы: голосов - 57, средняя оценка - 4.93
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18035 / 7738 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16

Сортировка словаря методом реконструкции

13.04.2014, 01:43. Показов 13246. Ответов 47

Студворк — интернет-сервис помощи студентам
Посмотрите, пожалуйста, может существует более оптимальный алгоритм.

Здесь я создаю 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
28
'Сортировка словаря методом вставок -> исходный словарь реконструируется
Sub SpecialSortDict(inDict)
    Dim arrPos: arrPos = inDict.keys                    'Инициализация массива позиций ключей словаря
    Dim arrTemp: arrTemp = inDict.Items                 'Виртуализация значений словаря
 
    Dim i, j, xItem
    For i = 1 To UBound(arrTemp)                        'Сортировка методом вставок
        For j = i To 1 Step -1
            If arrTemp(j) < arrTemp(j - 1) Then
                xItem = arrTemp(j)                      'Обмен значений
                arrTemp(j) = arrTemp(j - 1)
                arrTemp(j - 1) = xItem
                xItem = arrPos(j)                       'Обмен ключей
                arrPos(j) = arrPos(j - 1)
                arrPos(j - 1) = xItem
            Else
                Exit For
            End If
        Next
    Next
 
    Dim virtDict: Set virtDict = CreateObject("Scripting.Dictionary")
    For i = 0 To UBound(arrPos)                         'Расставляем значения в виртуальный словарь согласно массива ключей
        virtDict.Add arrPos(i), inDict(arrPos(i))
    Next
 
    Set inDict = virtDict
End Sub
Пример вызова:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Option Explicit
 
Sub main()
    Dim oScr: Set oScr = CreateObject("Scripting.Dictionary")
    
    oScr.Add "c", 8
    oScr.Add "aa", 1
    oScr.Add "bb", 3
    oScr.Add "a", 2
    oScr.Add "i", 4
    
    SpecialSortDict oScr
    
    Dim key
    For Each key In oScr.keys
        Debug.Print key & " - " & oScr(key)
    Next
    
End Sub
Переменные изначально нетипизированны. Код ориентирован на VBScript.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.04.2014, 01:43
Ответы с готовыми решениями:

Составить алгоритм и программу определения самых старых зданий, подлежащих реконструкции
Имеется список 60-ти зданий города, подлежащих реконструкции. Сведения о каждом здании содержат название микрорайона, улицу, номер дома и...

Сортировка словаря
Функция которая возвращает словарь. Но бывает что возвращает его не в том порядке в котором задавался. def multiply(vector, num): ...

Сортировка словаря
Всем привет. Есть словарь: babynames = { 'София, Софья': { 2012: ', 2010: ', 2005: ',

47
933 / 366 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
28.11.2023, 17:38
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от testuser2 Посмотреть сообщение
Допустим StrComp пишут быстрей обычного сравнения.
отнюдь. Для бинарного сравнения точно медленнее, для игнорирования регистра — по разному. Попробуйте сами…

Добавлено через 2 минуты
Если вы про квик, то там сравнение исключительно бинарное
1
1409 / 869 / 93
Регистрация: 08.02.2017
Сообщений: 3,719
Записей в блоге: 2
28.11.2023, 18:06
The trick, скажи пожалуйста, чисто гипотетически можно ли каким-нибудь таким образчиком получить доступ к данным ячеек Excel напрямую или хотябы насколько велики масштабы подобного исследования. Это чисто из любопытства, но, я думаю многим пользователям vba было бы это интересно.

Добавлено через 10 минут
Цитата Сообщение от Jack Famous Посмотреть сообщение
Для бинарного сравнения точно медленнее, для игнорирования регистра
Здесь я не спорю, все функции vb* очень униерсальны и вероятно по этому могут быть более медленны. Но есть еще момент, который может ускорить процесс - перемещение указателей вместо строк в массиве. Резоннный вопрос конечно всегда, есть ли в этом смысл и особая необходимость (или интерес как минимум) )

Добавлено через 16 минут
Пример с указателями
Кликните здесь для просмотра всего текста
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
Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
 
Private Type tpPrev
    Ptr As LongPtr
    Prv As LongPtr
End Type
 
#If Win64 Then
    Private Const ptrSz = 8
    Private Const pvDataOffset = 16
#Else
    Private Const ptrSz = 4
    Private Const pvDataOffset = 12
#End If
 
Dim p As Long, RestPtrStack() As tpPrev, pPtr() As LongPtr, Ptr() As LongPtr
Dim x
 
Sub Пример()
    Dim Arr()
    PtrInit
    x = vbNullString
    
    ReDim Arr(4)
    Arr(0) = "cc"
    Arr(1) = "ii"
    Arr(2) = "n"
    Arr(3) = "aa"
    Arr(4) = "l"
    PRDX_SortRecur_a1D_TU_PtrVarStr Arr, 0, 4
    
    pPtr(0) = VarPtr(x) + 8: Ptr(0) = 0
    ReleaseAllPtrs
End Sub
 
Sub PRDX_SortRecur_a1D_TU_PtrVarStr(a1D(), LBnd&, UBnd&)
Dim i&, j&, pTmp As LongPtr ', x, y
 
i = LBnd: j = UBnd ': x = a1D((LBnd + UBnd) \ 2)
pPtr(0) = VarPtr(x) + 8: Ptr(0) = StrPtr(a1D((LBnd + UBnd) \ 2))
 
Do
    While a1D(i) < x: i = i + 1: Wend
    While x < a1D(j): j = j - 1: Wend
    If i <= j Then
'        y = a1D(i): a1D(i) = a1D(j): a1D(j) = y
        pPtr(0) = VarPtr(a1D(i)) + 8: pTmp = Ptr(0): Ptr(0) = StrPtr(a1D(j))
        pPtr(0) = VarPtr(a1D(j)) + 8: Ptr(0) = pTmp
        i = i + 1: j = j - 1
    End If
Loop Until i > j
 
If LBnd < j Then PRDX_SortRecur_a1D_TU_PtrVarStr a1D, LBnd, j
If i < UBnd Then PRDX_SortRecur_a1D_TU_PtrVarStr a1D, i, UBnd
End Sub
 
Sub PtrInit()
    Dim ppvData1 As LongPtr, ppvData2 As LongPtr
    ReDim RestPtrStack(1): ReDim pPtr(0): ReDim Ptr(0)
    CopyMemory ppvData1, ByVal VarPtr(p) + ptrSz * 2, ptrSz
    ppvData1 = ppvData1 + pvDataOffset
    RestPtrStack(0).Ptr = ppvData1
    RestPtrStack(0).Prv = VarPtr(pPtr(0))
    CopyMemory ppvData2, ByVal VarPtr(p) + ptrSz * 3, ptrSz
    ppvData2 = ppvData2 + pvDataOffset
    RestPtrStack(1).Ptr = ppvData2
    RestPtrStack(1).Prv = VarPtr(Ptr(0))
    CopyMemory ByVal ppvData1, ppvData2, ptrSz
End Sub
 
Sub ReleaseAllPtrs()
    Dim i&
    For i = 0 To UBound(RestPtrStack)
        CopyMemory ByVal RestPtrStack(i).Ptr, RestPtrStack(i).Prv, ptrSz
    Next
End Sub
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18035 / 7738 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
28.11.2023, 18:12  [ТС]
Цитата Сообщение от Jack Famous Посмотреть сообщение
ну, как бы, тут смотря, что нужно — исследовать алгоритм/возможность или получить результат. Мой вариант — для второго подхода. Зачем сортировать ключи словаря вместе со значениями, если не использовать потом их в виде массивов — мне непонятно. А, если нужно как раз это, то почему бы не отойти от словаря и сразу перейти к массивам (благо, их получение происходит очень быстро).
Да очень разные бівают ситуации. Конкретный код писался под этот скрипт.

С помощью словаря создавалось подобие связанной таблицы по полю PID (у VBScript нет возможности создавать структуру):
Code
1
2
3
4
5
6
7
8
9
10
    set oSCR_t1 = CreateObject("Scripting.Dictionary")
    set oSCR_t2 = CreateObject("Scripting.Dictionary")
    'PID -> Name
    set oSCR_PID = CreateObject("Scripting.Dictionary")
    'PID -> Путь и параметры командной строки
    set oSCR_path = CreateObject("Scripting.Dictionary")
    'PID -> Service
    set oSCR_Serv = CreateObject("Scripting.Dictionary")
    'PID -> ParentPID
    set oSCR_parentPID = CreateObject("Scripting.Dictionary")
Затем с помощью алгоритма сортировки словаря через реконструкцию, такую таблицу можно отсортировать по любому из полей.
Можно конечно как вы предлагаете на месте отсортировать 2 массива, и сразу заюзать не рекунструируя словарь. Но вызвать функцию, передав пареметром словарь и на выходе получить уже готовый - так гораздо удобнее. Конечно, всё упирается на т/з и кол-во элементов. В любых других ситуауциях с большим объемом данных здесь стоит юзать БД.
0
Модератор
10068 / 3913 / 886
Регистрация: 22.02.2013
Сообщений: 5,863
Записей в блоге: 79
28.11.2023, 21:10
Цитата Сообщение от testuser2 Посмотреть сообщение
The trick, скажи пожалуйста, чисто гипотетически можно ли каким-нибудь таким образчиком получить доступ к данным ячеек Excel напрямую или хотябы насколько велики масштабы подобного исследования. Это чисто из любопытства, но, я думаю многим пользователям vba было бы это интересно.
Я уверен что у разных версий офиса ячейки будут лежать в разных местах, поэтому прямой доступ не имеет особого смысла т.к. с любой новой версией все может быть изменено.
2
933 / 366 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
29.11.2023, 09:42
Цитата Сообщение от The trick Посмотреть сообщение
Я уверен что у разных версий офиса ячейки будут лежать в разных местах
именно так. Если говорим об "xlsx/xlsm", то в структуре книги (открыть как архив): \xl\worksheets\sheenN.xml
У "*.xlsb" там же будут бинарники, а "*.xls" (который многие до сих пор активно используют, не давая умереть и облегчить жизнь программистам) — вообще борода полная, не искал.
Помним, что, хоть из хмл спарсить данные можно очень быстро, но этот хмл ещё нужно скопировать (чтобы добраться до содержимого) из книги (Namespace), а это тоже время — и немалое, если в хмл много инфы.
Нужно учесть, что в хмл может быть НЕ ВСЯ инфа с листа. Короче говоря, не советую… Можно ADODB попробовать для доступа, но я не стал из-за огромного количества нюансов и неизбежной необходимости всё самому тестить.

P.S.: в предыдущем посте, опять забыл, что мы тут все друзяшки и "на ты" общаемся
0
1409 / 869 / 93
Регистрация: 08.02.2017
Сообщений: 3,719
Записей в блоге: 2
29.11.2023, 13:20
Цитата Сообщение от Jack Famous Посмотреть сообщение
именно так. Если говорим об "xlsx/xlsm"
Я немножко другое имел в виду - расположение данных ячеек, в озу, когда документ загружен в память..
0
933 / 366 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
29.11.2023, 15:49
testuser2, огого
Ну, это будет НАМНОГО сложнее даже непростого разбора xml, если вообще возможно.
Да — профит может быть впечатляющий, но кто возьмётся за "копание" …
Чур не я

Добавлено через 9 минут
P.S.: плохо прочёл …

1. Если книга открыта, то найти в ней что-то не так сложно (и я очень удивлюсь, что данные книги хранятся в оперативной памяти).
Да - если бы было что-то типа строки со всеми данными листа — для каждого листа, то парсинг такой строки можно выполнить в разы быстрее, чем через Find или массивы.
Но такой поиск — довольно нишевая специфика. Мне, например, пока не нужно было ни разу.

2. Другое дело — получение данных из закрытых книг.
Большое количество времени тратится просто на открытие (а на корявой винде, как у меня ранее на работе — и на закрытие) книги.
И вот, если сделать инструмент быстрого получения данных с листа и/или структуры книги (имена листов и их видимость), то вот такая штука мне бы очень пригодилась.

У меня есть парсер workbook.xml — для получения структуры книги. Работает невероятно быстро.
Но, к сожалению, данные ко мне попадают в том числе в бинарных и старых книгах, что сводит на нет этот вариант.

P.P.S.: мы отошли от темы
0
1409 / 869 / 93
Регистрация: 08.02.2017
Сообщений: 3,719
Записей в блоге: 2
29.11.2023, 16:04
Цитата Сообщение от Jack Famous Посмотреть сообщение
Да - если бы было что-то типа строки со всеми данными листа
Скорей всего это в вид массива, но люди, делающие xll, наверное, это знают лучше, у них-то он есть прямой и законный доступ к данным, а в vba лишь копирование этих данных при обращении к объектам листа.
Фактически, как я это представляю, достаточно было бы
1) сдлать xll-ку, с функцией, которая возвращает указатель на начало некоего массива данны
2) знать структуру этих данных
Если я конечно не ошибаюсь в представлении того, что эо массив, т.е. некий непрерывный участок памяти. Еще один момент, что может быть память Экселя может быт как-то изолирована от "вторжения извне" (из vba).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.11.2023, 16:04

Сортировка словаря
##Дан словарь. Помогите остортировать его по значению Номер Dictionary = {'№':,'1':,'2':,'3':} print...

Сортировка словаря
database = { &quot;Группа1&quot;:, , ], &quot;Группа2&quot;:, ] } def cout2(groupname): for key in...

сортировка словаря
при запуске программы создается пустой словарь в процессе работы добавляются элементы. причем первое значение всегда число. при...

Сортировка словаря по ключу
Как отсортировать Dictionary &lt;int, Vector3&gt; по ключу, по возрастанию? Метода Sort() для словаря так сходу не нашёл. Надо компаратор...

Сортировка ключей словаря
Здравствуйте:) Существует словарь следующего вида: {'35': 1, '45': 2, '56': 3, '76': 4, '24': 5} Нужно отсортировать ключи данного...


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

Или воспользуйтесь поиском по форуму:
48
Ответ Создать тему
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 31.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru