powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Сортировка строкового/числового массива в VBA
20 сообщений из 20, страница 1 из 1
Сортировка строкового/числового массива в VBA
    #36985289
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Необходимо отcортировать одномерный массив строк используя только VBA . Пузырьковый метод в топку. На форуме не раз упоминали про copymemory, однако нигде не нашел конечного варианта функции/процедуры, имеющей на входе массив, а на выходе, например, массив индексов.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36985398
Deggasad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
посмотри в разделе Visual Basic, а не Microsoft Office
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36985473
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloder,

тут есть сортировка рекордсетом, если чуток раскурить будет вам легко массив индексов
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36985771
paveloder,

вариантов кагбэ тьма. Вот парочка из классики:
Quick sort
Shell sort
См. комментарии для заточки под строки.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36986570
Aster32
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
paveloder
1. Запишите свой строковый массив в столбец ячеек рабочего листа excel.
2. Примените к рабочему листу встроенный метод Worksheet.Sort
3. Считайте значения отсортированного слобца ячеек обратно в строковый массив.
4. Готово!

Все условия задачи соблюдены. Использован именно VBA, а не VB.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36986631
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shamanus,

в свойстве Sort нельзя указывать поле Variant?
приведенный ниже код выдает ошибку,
но работает, если делать сортировку числового массива по полю adInteger рекордсета
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Private Sub RecordsetSort(ByRef SortArray())
    Dim RS As New ADOR.Recordset
    Dim k As Long
    Dim lb As Long
    Dim ub As Long

    lb = LBound(SortArray)
    ub = UBound(SortArray)
    RS.Fields.Append "ArrValue", DataTypeEnum.adVariant
    RS.Open
    For k = lb To ub
        RS.AddNew
        RS!ArrValue = SortArray(k)
        RS.Update
    Next k
    RS.Sort = "ArrValue ASC"
    Erase SortArray
    ReDim SortArray(lb To ub)
    RS.MoveFirst
    For k = lb To ub
        SortArray(k) = RS!ArrValue
    Next k
    RS.Close
End Sub
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36986949
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloder,

а как вы себе представляете сортировку массива вариант?
что раньше идет, "2" или "10"?
с точки зрения текста идет так
Шапка1102

а с точки зрения чисел
Шапка1210ясное дело нужно тут заводить единый тип данных. Если данные типа Variant, то лучше наверное текст.
код готовый
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Private Sub RecordsetSort(ByRef SortArray() As Variant)
    Dim RS As New ADOR.Recordset
    Dim k As Long
    Dim lb As Long
    Dim ub As Long

    lb = LBound(SortArray)
    ub = UBound(SortArray)
    RS.Fields.Append "ArrValue", adChar,  35 , adFldIsNullable
    RS.Open
    For k = lb To ub
        RS.AddNew
        RS!ArrValue = CStr(SortArray(k))
        RS.Update
    Next k
    RS.Sort = "ArrValue"
    Erase SortArray
    ReDim SortArray(lb To ub) As Variant
    RS.MoveFirst
    For k = lb To ub
        SortArray(k) = RS!ArrValue
        RS.MoveNext
    Next k
    RS.Close
End Sub
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Sub test()
Dim x() As Variant
ReDim x( 1  To  10 ) As Variant
For i =  1  To  10 
    x(i) = i
    Debug.Print x(i)
Next i

Call RecordsetSort(x)

For i =  1  To  10 
    Debug.Print x(i)
Next i
End Sub
и asc идет по умолчанию, только desc надо писать. А еще забыли MoveNext курсору делать.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36986962
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати и erase и redim массиву тоже совсем не стоит делать. Размерность то остается прежней.
А если Вам нужны индексы то я бы сделал так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Private Sub RecordsetSort(ByRef SortArray() As Variant)
    Dim RS As New ADOR.Recordset
    Dim k As Long

    RS.Fields.Append "ArrValue", adChar,  35 , adFldIsNullable
    RS.Fields.Append "Ind", adInteger
    RS.Open
    For k = LBound(SortArray) To UBound(SortArray)
        RS.AddNew
        RS!ArrValue = CStr(SortArray(k))
        RS!ind = k
        RS.Update
    Next k
    RS.Sort = "ArrValue"
    RS.MoveFirst
    For k = LBound(SortArray) To UBound(SortArray)
        SortArray(k) = RS!ind
        RS.MoveNext
    Next k
    RS.Close
End Sub

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Sub test()
Dim x() As Variant
ReDim x( 1  To  10 ) As Variant
For i =  1  To  10 
    x(i) = i
    Debug.Print x(i)
Next i

Call RecordsetSort(x)
For i =  1  To  10 
    Debug.Print x(i)
Next i
End Sub
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36989423
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стоит признать, что сортировка массива методом QuickSort предпочтительнее RecordSet. Несмотря на то, что сортировка внутри RecordSet происходит очень быстро, очень большое время убивается на то чтобы записать массив в RS и наоборот. Особенно много времени уходит на запись.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36989802
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloderСтоит признать, что сортировка массива методом QuickSort предпочтительнее RecordSet. Несмотря на то, что сортировка внутри RecordSet происходит очень быстро, очень большое время убивается на то чтобы записать массив в RS и наоборот. Особенно много времени уходит на запись.
Вы правы, на маленьких массивах побеждает QuickSort, в общем для потомков хронометражи различными методами

сделал вот таким кодом сортировку,
сортировка по убыванию
Код: plaintext
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.
Sub test()
Dim x() As Variant
elem =  1000000 
ReDim x( 1  To elem) As Variant
m = Now
    For i =  1  To elem
        x(i) = CStr(i)
    Next i
Debug.Print "Время заполнения массива:" & Format(Now - m, "s")
m = Now
Call RecordsetSort(x)
Debug.Print "Время сортировки:" & Format(Now - m, "s")
Debug.Print "Первый элемент массива:" & x( 1 )


m = Now
For i =  1  To elem
    x(i) = CStr(i)
Next i
Debug.Print "Время заполнения массива:" & Format(Now - m, "s")

m = Now
Call QuickSort(x, , True)
Debug.Print "Время сортировки:" & Format(Now - m, "s")
Debug.Print "Первый элемент массива:" & x( 1 )

End Sub
получил вотДля словВремя заполнения массива:0Время сортировки:26Первый элемент массива:999999 Время заполнения массива:0Время сортировки:28Первый элемент массива:999999
поменял типы на Double
и формулу наполнения массивам изменил на
Код: plaintext
 x(i) = i+i/ 1000 
также пришлось сократить количество элементов до 30тыс т.к. 1млн тупо не дождался
Для чиселВремя заполнения массива:0Время сортировки:1Первый элемент массива:30030Время заполнения массива:0Время сортировки:48Первый элемент массива:30030Получается тут рекордсет побыстрее.
Теперь проведу проверку на 5000 раз сортировать массивы по 100 элементов.
код такой
код такой
Код: plaintext
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.
Sub test()
Dim x() As Variant
elem =  100 
progonov =  5000 

ReDim x( 1  To elem) As Variant

    m = Now
For l =  1  To progonov
    For i =  1  To elem
        x(i) = i + i /  1000 
    Next i
Call RecordsetSort(x)
Next l
Debug.Print "Время сортировки:" & Format(Now - m, "s")
  '---------------------------
    m = Now
For l =  1  To progonov
    For i =  1  To elem
        x(i) = i + i /  1000 
    Next i
Call QuickSort(x, , True)
Next l
Debug.Print "Время сортировки:" & Format(Now - m, "s")

End Sub
результаты тестов
первая строка - рекордсет, вторая квиксорт
Результат для чиселВремя сортировки:10Время сортировки:3

Результат для словВремя сортировки:10Время сортировки:2
изменим массив на 1000 элементов и 500 прогонов
Результат для 1000 словВремя сортировки:10Время сортировки:5
Результат для 3000 словВремя сортировки:12Время сортировки:7
Результат для 10000 словВремя сортировки:22Время сортировки:17
ну и сделал хронометраж сортировки 1 млн. элементов
хронометражВремя записи:16Время сортировки:3Время чтения:6резюме запись занимает 64% времени. Но зато когда записан - quick sort отдыхает. 3 секунды к 28.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36990270
Дорогой Shamanus
я, конечно, понимаю, что это
Код: plaintext
1.
2.
    For i =  1  To elem
        x(i) = i + i /  1000 
    Next i
вряд ли было сделано специально, но за такие фокусы из-за салуна выкинули бы сквозь дверь. Потому что это подтасовка, вольная или невольная. Если невольная, то почитай худший случай для QuickSort в любом описании алгоритма, или хотя бы в комментарии к реализации, на которую есть ссылка выше.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36990885
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Согласен с 13-й квартал с точки зрения подтасовки. Массив для теста лучше делать рандомным.

Однако, Shamanus, какой код для QuickSort вы используете? Я взял за образец приведенный на этом форуме код .
Вот конечный вариант:
QuickSortNonRecursive
Код: plaintext
\nPrivate Sub QuickSortNonRecursive(ByRef SortArray(), Optional Descending As Boolean)\n    Dim i As Long, j As Long, lb As Long, ub As Long\n    Dim stack() As QuickStack, stackpos As Long, maxstackpos As Long, stposArrMax As Long, ppos As Long, pivot As Variant, swp\n    \n    lb = LBound(SortArray)\n    ub = UBound(SortArray)\n    stposArrMax =  16 \n    ReDim stack(stposArrMax)\n    \n    stackpos =  1 \n    maxstackpos =  1 \n    stack( 1 ).Low = lb\n    stack( 1 ).High = ub\n    Do\n        lb = stack(stackpos).Low\n        ub = stack(stackpos).High\n        stackpos = stackpos -  1 \n        Do\n            ppos = (lb + ub) \\  2 \n            i = lb: j = ub: pivot = SortArray(ppos)\n            Do\n                While IIf(Descending, SortArray(i) > pivot, SortArray(i) < pivot): i = i +  1 : Wend\n                While IIf(Descending, pivot > SortArray(j), pivot < SortArray(j)): j = j -  1 : Wend\n                If i > j Then Exit Do\n                swp = SortArray(i): SortArray(i) = SortArray(j): SortArray(j) = swp\n                i = i +  1 \n                j = j -  1 \n           Loop While i <= j\n\n            If i < ppos Then\n                stackpos = stackpos +  1 \n                If stackpos > maxstackpos Then maxstackpos = stackpos\n                If stackpos > stposArrMax Then stposArrMax = stposArrMax *  2 : ReDim Preserve stack(stposArrMax)\n                stack(stackpos).Low = i\n                stack(stackpos).High = ub\n                ub = j \n            Else\n                If j > lb Then\n                    stackpos = stackpos +  1 \n                    If stackpos > maxstackpos Then maxstackpos = stackpos\n                    If stackpos > stposArrMax Then stposArrMax = stposArrMax *  2 : ReDim Preserve stack(stposArrMax)\n                    stack(stackpos).Low = lb\n                    stack(stackpos).High = j\n                End If\n                lb = i\n            End If\n        Loop While lb < ub\n    Loop While stackpos\nEnd Sub\n

Данный QuickSort сортирует одинаково быстро как и приведенный вами пример упорядоченного числового массива i+i/1000 с миллионом записей, так и рандомные числовые/строковые массивы.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991120
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloder, 13-й квартал

ну во первых
я так понимаю Вы предлагаете сортировать список 1,2,3 по возрастанию для оценки эффективности алгоритма? Мне почему то казалось, что оценка задержки в "худшем" случае и есть оценка эффективности или будем надеяться, что он никогда не наступит, а значит машина времени создана алгоритм идеален?

а во вторых
я наоборот признал более высокую эффективность quick sort на массивах. Что Вас не устраивает? Несмотря на то, что метод sort для Recordset в разы быстрее - скорость записи массива и чтения из recordset это преимущество сводит на нет.

и наконец в третьих - мой пост следует читать так:
Вывод: если данные находятся в массиве - сортируйте QuickSort, если уже лежат в Recordset, то метод Sort быстрее чем даже QuickSort - не говоря уж о сэкономленных миллисекундах на чтении и записи этого Recordset
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991282
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shamanusоценка задержки в "худшем" случае и есть оценка эффективности
спорный вопрос

мое замечание касается исключительно вашего QuickSorta: почему работает медленно?
возможно что мой вариант учитывает крайние случаи, а ваш нет, но это только предположение
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991361
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloderспорный вопрос ну как сказать. В таком случае те кто пишут многопользовательские приложения могли бы проводить тесты скорости на 1 м пользователе.
А те кто разрабатывают базы данных могли бы тестировать скорость на селекте 10 записей из индексированной таблицы.

Только обычно когда тестируют СУБД перед покупкой пытаются запустить самый невероятно сложный селект, который только попадался на практике.

впрочем у каждого свое мнение на этот счет. «Имхо у нас у всех имхастое» (с)

paveloderмое замечание касается исключительно вашего QuickSorta: почему работает медленно? Думаю у Вас есть возможность проверить работу того алгоритма который использовал я из этого поста 9862385 и своего. Заодно увидим эффективность каждого из алгоритмов.
Ваш код у меня запустить не удалось из-за неизвестного типа данных, а искать библиотеку или описание лень..
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991412
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShamanusВаш код у меня запустить не удалось из-за неизвестного типа данных

сорри забыл указать в своем посте описание типа
Код: plaintext
1.
2.
3.
4.
Private Type QuickStack
    High As Long
    Low As Long
End Type
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991461
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloder,

код теста такой
Код: plaintext
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.
Public Declare Function GetTickCount Lib "kernel32" () As Long
Sub test()
Dim x() As Variant
Dim y() As Variant
elem =  10000 
Randomize
For l =  1  To  10 
m = GetTickCount
ReDim x( 1  To elem) As Variant
ReDim y( 1  To elem) As Variant
    For i =  1  To elem
        x(i) = Round(Rnd *  1000 ,  0 )
    Next i

    For i =  1  To elem
        y(i) = x(i)
    Next i
Debug.Print "Итерация " & l & "____________________________"
m = GetTickCount
Call QuickSortNonRecursive(x)
Debug.Print "Время сортировки QSNR:" & GetTickCount - m

m = GetTickCount
Call QuickSort(y, , True)
Debug.Print "Время сортировки QS:" & GetTickCount - m
Next l
End Sub
код выводит время в миллисекундах
итог для 10 тыс записей где x(i) = Round(Rnd * 1000, 0)Итерация 1____________________________
Время сортировки QSNR:63
Время сортировки QS:31
Итерация 2____________________________
Время сортировки QSNR:47
Время сортировки QS:31
Итерация 3____________________________
Время сортировки QSNR:62
Время сортировки QS:32
Итерация 4____________________________
Время сортировки QSNR:47
Время сортировки QS:31
Итерация 5____________________________
Время сортировки QSNR:62
Время сортировки QS:32
Итерация 6____________________________
Время сортировки QSNR:46
Время сортировки QS:32
Итерация 7____________________________
Время сортировки QSNR:47
Время сортировки QS:31
Итерация 8____________________________
Время сортировки QSNR:63
Время сортировки QS:31
Итерация 9____________________________
Время сортировки QSNR:47
Время сортировки QS:31
Итерация 10____________________________
Время сортировки QSNR:63
Время сортировки QS:31
для 5тыс записей где x(i) = Round(Rnd * 1000, 2)Итерация 1____________________________
Время сортировки QSNR:31
Время сортировки QS:16
Итерация 2____________________________
Время сортировки QSNR:31
Время сортировки QS:16
Итерация 3____________________________
Время сортировки QSNR:31
Время сортировки QS:15
Итерация 4____________________________
Время сортировки QSNR:16
Время сортировки QS:16
Итерация 5____________________________
Время сортировки QSNR:31
Время сортировки QS:16
Итерация 6____________________________
Время сортировки QSNR:31
Время сортировки QS:15
Итерация 7____________________________
Время сортировки QSNR:32
Время сортировки QS:15
Итерация 8____________________________
Время сортировки QSNR:16
Время сортировки QS:16
Итерация 9____________________________
Время сортировки QSNR:16
Время сортировки QS:15
Итерация 10____________________________
Время сортировки QSNR:32
Время сортировки QS:15
ну и для проверки 10 тыс записей с x(i) = CStr(Round(Rnd * 1000, 0))Итерация 1____________________________
Время сортировки QSNR:78
Время сортировки QS:63
Итерация 2____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 3____________________________
Время сортировки QSNR:79
Время сортировки QS:78
Итерация 4____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 5____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 6____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 7____________________________
Время сортировки QSNR:94
Время сортировки QS:62
Итерация 8____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 9____________________________
Время сортировки QSNR:78
Время сортировки QS:78
Итерация 10____________________________
Время сортировки QSNR:79
Время сортировки QS:78
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36991469
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел ошибку в направлении сортировки, в коде разные применялись. Но на итоги это не повлияло. Можете перепроверить.
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36992354
Фотография paveloder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shamanus,

а теперь протестируйте таким же макаром x(i)=i на 1000 элементов
ваш QuickSort встанет

думаю, что разница наших методов состоит в первоначальном приближении в каждой итерации стэка: в вашем берется значение конца стэка, в моем - значение середины стэка
...
Рейтинг: 0 / 0
Сортировка строкового/числового массива в VBA
    #36992468
Фотография Shamanus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
paveloderдумаю, что разница наших методов состоит моего метода тут нет. я и Ваш и другой взял на этой ветке форума.

Тестировать больше ничего не буду, уже все закрыл не сохраняя. Хотите возьмите коды для теста и потестируйте сами.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Сортировка строкового/числового массива в VBA
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]