Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: Пред. 1 2 3 4 5 6 7 8 След.
RSS
Сортировка в двумерном массиве VBA Excel, Написал тут небольшую процедурку, может кому будет полезна
 
Кстати,  если нужна сортировка именно одномерного массива строк, то тут в теме есть ссылка на сортировку через системные библиотеки. Тестил дома. 1кк массив со строкой 100 обрабатывался на домашнем чуде  без малого 2 сек. По числам встроенный сортер косячит и не досортировывает (тестировал на Double), но скорость конечно не сравнимая ни с одним сортером на VBA - 0.78 или около этого на миллионе чисел и моем замшелом компе..
 
Возможно, но хочется удовлетворить творческие потребности, а также попрактиковаться в C#, например, можно... И скомпилировать еще более быструю процедуру, но гарантированную свою, а то нет задач и нет практики. :)
Изменено: AAF - 28 фев 2018 15:17:01
 
AAF, лично я с C# не знаком, поэтому больше времени уйдет на освоение языка) Ну со сферой применения будут проблемы, т.к. пишу в основном для форума и работы, а на работе решили перейти на профессинольное профильное ПО без всяких экселей и мой проект-долгожительл скоро останется безработным :)
 
Данный файл использует код выложенный в сообщении 116
Все массивы не привязаны к Option Base, а SortStr не привязано к Option Compare. Массив индексов не требует общего LBound с массивом данных.
SortBin и SortStr являются отдельными функциональными процедурами. SortAll, используя их, является "менеджером" процедур для упрощения использования и ускорения работы с сортровкой по числовой части с помощью вмонтированного сепаратора.
Приложенный файл содержит код самих сортровщиков (SortBin, SortStr, SortAll), а также тестовый стенд с генератором таблиц, допускающий использование вложенной сортировки.
Содержание модулей кода:
SortCode содержит процедуры готовые к применению по сортировке
SamleCode содержит описание и примеры к применению вышеуказанного кода
GeneratorTable содержит код относящийся к организации стенда
При сортировке через SortAll данные складываются следующим образом:
AZ - числа, текст, пустые строки, empty
ZA - текст, пустые строки, числа, empty
Если есть вопросы или аргументы отличные от использованных в данной реализации пишите и задавайте вопросы...
Изменено: AAF - 2 мар 2018 15:32:54
 
Привет!
Цитата
AAF написал:
задавайте вопросы
Спасибо. Скачал Ваш файл.
Debug - Complie VBA project = Type mismatch: array or user-defined type expected
На строке
Код
SortBin ДвумерныйМассив, 1, МассивИндексов, 1, 1, 10, 100
процедуры Sub SortStr_Sample()

Excel 2010
Сравнение прайсов, таблиц - без настроек
 
Цитата
Inexsu написал:
Type mismatch: array or user-defined type expected
Поданные массивы не соответствую заявленному типу (либо ДвумерныйМассив, либо МассивИндексов)
 
Цитата
AAF написал:
Поданные массивы
Ещё никто ничего не подавал :-)
Открыл скачанный файл, Alt+F11, Debug - Complie VBA project
Получил Type mismatch
У Вас ведь не так?
Сравнение прайсов, таблиц - без настроек
 
Цитата
AAF написал:
Если есть вопросы или ...
Спасибо за код, круто!
Пытаюсь протестировать...

1. Видимо ошибка в описании:
Код
Sub SortStr_Sample()
'...
SortBin ДвумерныйМассив, 1, МассивИндексов, 1, 1, 10, 100
'...
SortBin ДвумерныйМассив, 2, МассивИндексов, -1
Наверно подразумевался вызов SortStr ?

2. Если "Направл. сортировки" в тестовой таблице или в вызывающем модуле задать -1,
Код
Function SortAll
'... в последнем цикле:
  For i = LBound(a0) To UBound(a0): aResult(i, j) = a(a0(i), j): Next
выдает ошибку выхода за пределы диапазона.

PS Отладка показала, что массив a0 формируется неправильно - некоторые значения остаются нулевыми...

PPS Можете исправить? Или подсказать - что нужно изменить...
Изменено: SSL13 - 17 авг 2018 19:07:05
 
Приношу свои извинения, если что не так...
Как смогу - проверю, и, кроме того, код уже переписан, который использую....
Просто не было возможности ответить....
Внесу изменения в течение недели.
Еще раз приношу извинения... :(
Изменено: AAF - 18 авг 2018 14:08:51
 
Цитата
AAF написал:
Внесу изменения в течение недели.
Это здорово!
Сейчас использую SortAll с настройками по умолчанию, но
пришлось добавить отдельный перевертыш, т.к. требуется обратная сортировка.
И все равно быстрей, чем SortBin с собственной обратной сортировкой.
(Гоняю массивы по 750 000 строк примерно 1,2-1,5 сек.)

PS В качестве входного и выходного массива использую один и тот же: arr = SortAll(arr, 1)
Пробовал переделать под передачу массива по ссылке: SortAll arr, 1
чтоб исключить промежуточные копирования,
но почему-то получалось медленнее...
возможно из-за того, что в этом случае VBA воспринимает массив arr, как переменную Variant?...
Изменено: SSL13 - 19 авг 2018 18:09:09
 
Еще вариант, но по скорости намного скромнее последних здесь представленных:

Скрытый текст
Изменено: Anchoret - 19 дек 2018 18:30:19
 
Цитата
Anchoret: Спойлер в Internet Explorer ставить отказывается
режим BB-Code и тэги ["SPOILER"]["/SPOILER"] (без кавычек) — может сработать…
Изменено: Jack Famous - 19 дек 2018 16:33:25
Реквизиты для благодарности и контакты для связи — в профиле
 
Jack Famous, сработало)
 
ArraySort - СОМ библиотека на С++ (используется так же, как , к примеру, Dictionary, через CreateObject). Функционал (Тип данных: "String"):
1.Сортировка одномерных и двухмерных массивов
2.Удаление дубликатов в одномерных массивах
3.Вывод по одномерному и двухмерному массивам индексов по строкам или столбцам.
4.Сортировка по столбцам, строкам, целому массиву с выводом строки/столбцы, столбцы/строки.
5.Сортировка по 3 ключам (столбцам, строкам)
6.Размерность массива может начинаться с 0,1,2... и т.д. (любого положительного числа, вывод индексов в такой же размерности)
7.Обработка NULL - строк (перемещение на последние позиции)
8.Использованы параллельные алгоритмы сортировки.

Интерфейс класса:
Код
interface IVBA : IDispatch
{
    [id(1), helpstring("Array sort")] HRESULT ArraySort([in, out] VARIANT* array_in_out, [in,defaultvalue(0)] VARIANT_BOOL sort_order, [in, defaultvalue(-1)] LONG key_1, [in, defaultvalue(-1)] LONG key_2, [in, defaultvalue(-1)] LONG key_3, [in, defaultvalue(0)]  LONG sort_orientation,  [in, defaultvalue(0)]  VARIANT_BOOL delete_duplicates,[in, defaultvalue(0)]  VARIANT_BOOL out_array_index, [in, out, defaultvalue(0)] VARIANT* index_array_out);
 
};


array_in_out - указатель на массив (ввод/вывод).  
sort_order - порядок сортировки : 0-по возрастанию (по умолчанию), 1-по убыванию.
key_1 - ключи сортировки (индекс столбца или строки) по умолчанию - первый столбец/строка
key_2...
key_3...
sort_orientation - ориентация сортировки (0 - по строкам, 1 - по столбцам, 2- целый массив вывод строка-столбец, 3- целый массив вывод столбец-строка)
delete_duplicates - удаляем дубликаты (в одномерных массивах)
out_array_index - выводим индексы (тогда основной массив array_in_out - не меняется, выводятся данные в out_array_index)
out_array_index - одномерный массив с индексами (с учетом всех ключей)

Все параметры метода, кроме входящего массива - опциональные (с значениями по умолчанию - 0 (ключи-1))

Пример тестирования на VBA:
Скрытый текст

И самое интересное!
Результаты тестирования на 2-х млн. строк и 4-м столбцам:
Простая сорт. 1х массива, по возрастанию (по умолч.): 0,21875 сек.
Простая сорт.по убыванию 1x массива с удалением-34,55365%: 0,3046875 сек.
Вывод индексов для 1х массива, сортировка по убыванию:0,25 сек.
Простая сортировка 2х массива: 0,359375 сек.
Сортировка 2х массива по 5й строке: 0,3515625 сек.
Сортировка всего 2х массива - вывод строки/столбцы: 1,117188 сек.
Сортировка всего 2х массива - вывод столбцы/строки 1,195313 сек.
Вывод индексов для 2х массива, по указанному столбцу: 0,296875 сек.
Вывод индексов для 2х массива, по указанноq строке: 0,2890625 сек.
Сортировка 2х массива по 5,6,7й строке: 0,03125 сек.
Сортировка 2х массива по 3,4,5му столбцу: 0,9609375 сек.

Сортируйте в VBA и удаляйте дубликаты на скоростях С++ до 35 раз быстрее самого быстрого алгоритма (QuickSort) по типу данных: "String"
Исходники
Изменено: bedvit - 20 дек 2018 21:17:22
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, проведена огромная работа и Спасибо за возможность ею пользоваться!
Цитата
bedvit написал:
самого быстрого алгоритма (QuickSort).
Этот алгоритм самый быстрый при следующих вводных:
- массив одномерный или плевать на итоговый порядок строк (индексов) одинаковых значений. Ради эксперимента попробуйте отсортировать двумерный массив, где и в первом и втором "столбце" будут дубликаты.
- быстрейший, но только как универсал, или для определенных типов данных. Те-же числа можно отсортировать быстрее.
 
Anchoret, верно. Подправил "Тип данных: Строки".
«Бритва Оккама» или «Принцип Калашникова»?
 
Очередной вариант сортировщика текста в двумерке без проверки на пустоты и без необходимости доводки индексов.

Как он работает:
- формирует единую строку (кол-во сортируемых элементов * максимальную длину строки в массиве)
- конвертит в строку в байтовый массив
- в три прохода (от третьего символа, если их 3 или больше в максимуме строки, до первого) распределяет индексы по матрице
- доводка вставками до финала.
Сортер
Тестер
Время

На секунду с лишним быстрее варианта размещенного здесь ранее.
Есть подводные камни - если в каждой текстовой строке массива есть префикс в виде трёх одинаковых символов, то сортировка будет ну очееееень долгой :) Вероятно на длинных строках будет чуть медленнее - увеличится время набивания строки в сортере + разбивки ее на байты.
 
Anchoret, взял в тестирование)))
а зачем в конце кода Erase aa: Erase cc, ведь следующяя строка заканчивает процедуру и все переменные и так очистятся… Разве не быстрее убрать?…
Изменено: Jack Famous - 14 мар 2019 10:35:24
Реквизиты для благодарности и контакты для связи — в профиле
 
Jack Famous, Это на всякий пожарный + как я заметил используя процедуру для мониторинга памяти в начале этой темы, что не удаляя массивы в процедуре объем памяти занятый Excel растет.
 
Anchoret, спасибо - учту  ;)
Итак… Сравнил вашу сортировку с Excel'евской. Основное отличие в том, что в xl сортировка НЕ привязана к регистру, то есть "ааа", "АаА", "аАа" и "ААА" имеют одинаковый приоритет. У вас же "ЯЯЯ" будет стоять ПЕРЕД "ааа", как я понял — это из-за того, что в таблице символов сначала идут "ПРОПИСНЫЕ", а уже потом "строчные". Считаю это не совсем корректным и предлагаю сравнивать без учёта регистра. У меня на массиве (15 000,3) сортировка занимает ДО 10 мс, а значит запаса скорости более чем хватает.
Можно, конечно, сортировать сначала без учёта регистра (как xl), а при совпадении переходить на сравнение с учётом регистра, но это тот ещё геморрой, который сожрёт немало скорости, а пользы мало. Ещё у вас числа сортируются текстом, но как раз это я проблемой абсолютно не считаю  :)
Функция
Тестовый файл на DropMe
Изменено: Jack Famous - 14 мар 2019 12:01:01
Реквизиты для благодарности и контакты для связи — в профиле
 
Цитата
Jack Famous написал:
Считаю это не совсем корректным и предлагаю сравнивать без учёта регистра. У меня на массиве (15 000,3) сортировка занимает ДО 10 мс, а значит запаса скорости более чем хватает.
Вы не так давно утверждали, что Вы программист) Сможете переделать?
Цитата
Jack Famous написал:
Ещё у вас числа сортируются текстом
Цитата
Anchoret написал:
вариант сортировщика текста

П.С.: Будет время - добавлю вариант без учёта регистра)
 
Цитата
Anchoret: Вы не так давно утверждали, что Вы программист) Сможете переделать?
неужто на "слабо" берёте… В вашем варианте мне разобраться непросто, поэтому буду ждать обновлённой версии. Пока могу предложить только вариант "в лоб" (перевести "столбец" массива для сортировки в верхний регистр), что явно не самое лучшее…
Изменено: Jack Famous - 14 мар 2019 12:20:10
Реквизиты для благодарности и контакты для связи — в профиле
 
Jack Famous, Там распределение , поэтому только через U/LCase. Собственно Заменить одну строку кода ближе к началу процедуры и одну при дошлифовке вставками при сравнении.
 
Цитата
Anchoret: одну строку кода ближе к началу
BB = StrConv(dt, 128) на BB = StrConv(UCase$(dt), 128)?
Вторую часть найти не могу, но, думаю, что строки 47-51 функции…
Реквизиты для благодарности и контакты для связи — в профиле
 
Jack Famous, можно и эту... Правда не знаю сколько займет преображение строки в энное кол-во десятков/сотен тысяч символов к какому-либо регистру.
 
Цитата
Anchoret: сколько займет преображение строки
ну по-идее, явно меньше, чем в цикле каждый элемент (даже, если цикл по элементам и так есть). Ещё, возможно, что замена уже КОНВЕРТИРОВАННОЙ строки будет быстрее, но тут только тесты покажут истину…
Реквизиты для благодарности и контакты для связи — в профиле
 
Вариант с выбором Compare:
Скрытый текст

Оптимизировал по памяти и немного по скорости.
------------
Подправил код , который до этого не корректно работал с массивами с нижней границей = 0.
Изменено: Anchoret - 19 мар 2019 19:20:04
 
Anchoret, добрался наконец)) сначала хотел спросить, почему iComp не булево (напрашивается), но потом увидел, что StrComp напрочь отказывается с булевыми сотрудничать даже через двойное отрицание.

Большое вам спасибо за супершуструю функцию! Взял себе в постоянную работу  :idea:
Функция

P.S.: не хотели бы такую же функцию для сортировки одномерных массивов написать?  :)
Изменено: Jack Famous - 15 мар 2019 11:20:49
Реквизиты для благодарности и контакты для связи — в профиле
 
Jack Famous, почему именно функция?) Врядли ее можно приспособить для работы на листе... Но на вкус и цвет...
На тему одномерки:
- убираем параметр из процедуры/функции отвечающий за номер сортируемого "столбца" массива
- лезем внуть процедуры/функции сортировки и меняем все манипуляции с двумерным массивом на манипуляции с одномерным
- в конце, где идет сборка массива убираем один внутренний цикл с соотвюманипуляциями по замене

П.С.: По моим оценкам это самый шустрый сортер по тесту из написанных на VBA. Сравнивал с сортировщиком на базе квика внедренным в мой вариант Dictionary:
Код
StrBytesSort - time: 2,168 Array: 1000000/1 Str.Len: 15 - сортер представленный здесь
AL.txtSort sorting - time: 2,250 Array: 1000000/1 Str.Len: 15 - его клон с проверкой на пробелы внедренный в мой вариант Dictionary
AL.Sort sorting - time: 8,125 Array: 1000000/1 Str.Len: 15 - сортер на базе QuickSort краткой реализации

В общем последний не очень соответствует званию QuickSort.
 
Цитата
Anchoret: Врядли ее можно приспособить для работы на листе
да легко  :) аааа - я понял))) вы про вызов через "=" на листе… Да я уже давно свои процедуры в булевые функции переделал, чтобы прерывать по ошибке без дополнительных строк (Типа If Not UDF Then)
Код
Sub t()
Dim temp, tm!: temp = [_test].Value2: tm = Timer
If PRDX_ArraySort2x(temp, 3) Then MsgBox Format(Timer - tm, "0.000 sec"): [a1].Resize(UBound(temp,1),UBound(temp,2)).Value2=temp
End Sub
Цитата
Anchoret: На тему одномерки
не могли бы вы, пожалуйста, сами это сделать - я боюсь лезть)
Цитата
Anchoret: это самый шустрый сортер по тесту из написанных на VBA
полностью согласен  :)
Изменено: Jack Famous - 15 мар 2019 12:09:08
Реквизиты для благодарности и контакты для связи — в профиле
Страницы: Пред. 1 2 3 4 5 6 7 8 След.
Читают тему (гостей: 1)
Наверх