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

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

13.04.2014, 01:43. Показов 12362. Ответов 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
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
28.11.2023, 17:38
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от testuser2 Посмотреть сообщение
Допустим StrComp пишут быстрей обычного сравнения.
отнюдь. Для бинарного сравнения точно медленнее, для игнорирования регистра — по разному. Попробуйте сами…

Добавлено через 2 минуты
Если вы про квик, то там сравнение исключительно бинарное
1
1389 / 845 / 92
Регистрация: 08.02.2017
Сообщений: 3,601
Записей в блоге: 1
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
18033 / 7736 / 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
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
28.11.2023, 21:10
Цитата Сообщение от testuser2 Посмотреть сообщение
The trick, скажи пожалуйста, чисто гипотетически можно ли каким-нибудь таким образчиком получить доступ к данным ячеек Excel напрямую или хотябы насколько велики масштабы подобного исследования. Это чисто из любопытства, но, я думаю многим пользователям vba было бы это интересно.
Я уверен что у разных версий офиса ячейки будут лежать в разных местах, поэтому прямой доступ не имеет особого смысла т.к. с любой новой версией все может быть изменено.
2
932 / 365 / 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
1389 / 845 / 92
Регистрация: 08.02.2017
Сообщений: 3,601
Записей в блоге: 1
29.11.2023, 13:20
Цитата Сообщение от Jack Famous Посмотреть сообщение
именно так. Если говорим об "xlsx/xlsm"
Я немножко другое имел в виду - расположение данных ячеек, в озу, когда документ загружен в память..
0
932 / 365 / 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
1389 / 845 / 92
Регистрация: 08.02.2017
Сообщений: 3,601
Записей в блоге: 1
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
Ответ Создать тему
Новые блоги и статьи
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru