![]() |
[VBS] Сортировка текстовых строк с учётом директорий
Есть текстовые строки (именно строки, а не пути к существующим файлам)
Код:
\F1\1.txt Код:
\F0\ Код:
\f11.txt Код:
\F0\ Как это сделать? есть решение или алгоритм? это должна быть рекурсивная функция? через split("\") ? Скрытый текст
набросок для переменных Код:
Dim a(1 To 12) |
shadowbat, в списке только один символ (f или F) и он одинаковый во всех строках , или вместо него может быть смесь символов перед цифрами и они могут в разных строках свои?
|
Цитата:
это парсинг реальных путей файлов, но в виде строк, соответственно имена могут быть такие же как у реальных директорий и файлов - самые различные сам пока пишу на split() и ubound(split()) очень предварительный и полуправильный вариант
Код:
Sub Sort() |
не по алфавиту, а по директориям
Код:
FileIn = "Z:\Box_In\filein.txt" |
megaloman, работает
замена "\" на Chr(0) изящная, действительно AscW("\") мешает сравнивать строки, т.к. у него номер ниже/выше чем у алфавита а также выдаёт все строки в LCase регистре, что всё-таки является изменением, а не только сортировкой (понимаю, что без LCase сортировка в текущем виде не сработает, но факт остается фактом - после этой функции нужно производить дальнейшие действия со строками только в нижнем регистре, либо дополнительно восстанавливать изначальный регистр после функции) |
shadowbat, а можете рассказать, для чего Вам потребен список именно в таком виде?
|
Цитата:
|
shadowbat, спасибо, ясно.
|
Цитата:
подразумевается, что изначально в строках не было разнорегистровых дублей, иначе оба дубля получат одинаковый регистр (либо нижний либо изначальный) исправил лишнее добавление пустой строки в конце нового файла добавить после MsgBox out: и сохранение в файл соответственно заменить на out3 Код:
out2 = Split(out, vbCrLf) |
Цитата:
Вариант, где этого делать не надо. Не думал, что регистр в путях имеет какое-то значение
Код:
FileIn = "Z:\Box_In\filein.txt" |
megaloman,
во втором варианте сортировка чуть слетает и \f0\1.txt улетает наверх во время обработки out = (если f маленькая) (в первом сообщении я разнорегистр не учёл и указал \F0\1.txt, нужно заменить на \f0\1.txt, чтобы были разнорегистровые пути) вывод: Код:
\f0\1.txt (!) Код:
If InStr(1, MasF(j), D) <> 0 Then Код:
If InStr(1, LCase(MasF(j)), LCase(D)) <> 0 Then |
shadowbat, Исправил. См. предыдущий пост. Не очень понятно, как у Вас такое вышло, что пути разнорегистровые, если данные не руками вбиты. Однозначно сортировка сломается, если, например, добавить строки
\F222\222.txt \F000\000.txt то есть, когда есть пути файлов, а путей к их папке нет |
Упростил код. Увы, кривой вариант
Код:
FileIn = "Z:\Box_In\filein.txt" |
Цитата:
отличие ниже (может кому-то понадобится именно такая сортировка) Скрытый текст
![]() |
shadowbat,
Исправил
Код:
FileIn = "Z:\Box_In\filein.txt" |
megaloman, прекрасный код, максимально локаничный, обвязка даже больше места занимает, чем сама действующая часть
|
Цитата:
Скрытый текст
Код:
Sub T() + защита Код:
If Left(s, 1) <> "\" And Mid(s, 2, 2) <> ":\" Then s = "\" & s |
shadowbat,
Не знаю, зачем нужно делать для массива, но я бы его определил вот так:
Код:
a = Array("\F0\", _ |
если кто-то будет в дальнейшем пользоваться:
SortMas это узкое горлышко из-за метода пузырька на 70 000 файлах ориентировочное время исполнения 1 час - огромное число для такого "небольшого" количества файлов в DirC для коллекций, к примеру, та же сортировка должна выполняться ещё дольше - 390 часов (из-за перемножения операций 70 000 x 70 000) (один прогон 70000 раз занимает 20 секунд) нужно обязательно менять метод пузырька на любой другой. (даже хотя бы через выгрузку на лист (в две колонки обычную и lcase) + родную сортировку ActiveSheet.Sort по lcase + загрузку назад) |
shadowbat, А Вы не говорили, что это VBA в Excel, это стльно меняет дело. Колитесь, откуда берутся строки и куда они деваются потом. Почему надо сохранять регистр - внутри сортировки любое лишнее действие ест много времени
|
Цитата:
Цитата:
строки берутся из FSO, который загоняет их в коллекцию простым прогоном по всему дереву (Dir не понимает юникод в именах) далее две коллекции с деревьями объединяются, отрезается начальный каталог, убираются дубли, остаётся коллекция с уникальными строками из обеих папок (в первом сообщении первый код под фразой "Есть текстовые строки:") Цитата:
учитывать разный регистр необходимо, потому что в одной папке может быть \Folder\File1.txt , а в другой \FOLDER\file1.txt , в Windows это один и тот же путь, а при обработке строка "\Folder\File1.txt" не равна "\FOLDER\file1.txt", поэтому и сортируем через lcase, а результат выдаём в оригинальном регистре да и к тому же этот переключатель регистра легко можно настроить. на самом деле их два. 1. сортировка с учетом регистра (или без учета) и 2. выдача результата в оригинальном регистре или в нижнем/верхнем это всё кому как удобнее и на метод пузырька не влияет в данном случае, найти удобный/быстрый метод сортировки это тоже не проблема, методов сортировки много, вплоть до внешних библиотек, я всего лишь уточнил, что метод сортировки необходимо изменить на любой другой, а на какой именно уже не так важно вообще, во всей этой теме гениальные строки с заменой слеша на Chr(0) и подстановка перед файлом Chr(1), что позволяет сортировать строки любым обычным способом, который подходит для сортировки текста и делать любую обвязку кому как удобнее, это не предмет спора вообще |
shadowbat, Подозреваю, сортировка не нужна вовсе. По голому имени нельзя узнать, файлы или изменены или равны. Надо четкая постановка. Возможно, есть готовый софт для этого. И зачем при сравнении наличия файлов надо перечислять имена директорий? Почему не ограничиться только полными именами файлов?
|
Цитата:
Цитата:
вопрос был конкретно по сортировке директорий, представленных в виде строк. несколько разных готовых .exe софтов для сравнения двух папок, конечно, тоже существует на просторах интернета. часто подаётся под соусом "синхронизация", что, по мне, является совершенно отдельной задачей. например существует сравнение текстовых и бинарных файлов, но не существует синхронизации файлов, потому что впихивать содержимое одного файла в другой никому не приходит в голову Цитата:
у каких то людей/программ только файлы, у иных и файлы и папки, а может у кого-то список только папок. сортировка только файлов без учёта папок является полумерой это как сортировать строки текста без учёта спец символов !@№;%:?, не во всех же строках они имеются, зачем их учитывать при сортировке? |
shadowbat, ну, вот, я как-то вполне обхожусь Far Manager'ом с парой-тройкой плагинов плюс внешним CloneSpy для покрытия всего спектра своих задач по полуавтоматическому сравнению каталогов и файлов.
Для сортировки строк, занимающей длительное время, есть смысл применять либо System.Collections.ArrayList/System.Collections.Sortedlist из .Net (возможно, потребуется однократно зарегистрировать библиотеку), либо базу данных в памяти. |
Цитата:
|
К сожалению при выгрузке на лист есть две проблемы:
1. Chr(0) не обрабатывается, и обрезается, таким образом вместо Chr(0) Chr(1) необходимо использовать например Chr(1) Chr(2) 2. Родная сортировка Exl не учитывает символы Chr(0-31), таким образом Chr(0) и Chr(1) нужно заменить на любой другой (невстречающийся) набор печатных символов с номером >31 согласно таблице ascii, например &0& и &1& , в идеале нужно использовать любые "неправильные" символы \ / : * ? " < > | |
Вложений: 1
shadowbat, Пробуйте, интересно, быстрее сортировка?
|
Цитата:
2. в цикле For i = N1 + 1 To N2 идёт накопление и Exl ненадолго подвисает на примерно i=16000-25000 (возможно точное число зависит от конфигурации машины), если добавить строку If i Mod 1000 = 0 Then Debug.Print i , то видно как скорость печати постепенно уменьшается до (Не отвечает). при этом в диспетчере задач видно, что Exl продолжает работать и в конечном итоге отвисает. 65000 строк сортирует за 2-3 минуты, что конечно быстрее прошлого значения 3. при сохранении 65000 длинных строк со средней длиной 50 была ошибка. на строке .Write SS при работе с 65000 строками выдал "Ошибка: Run-time error '5': Invalid procedure call or argument", если строк меньше, то сохраняет нормально. если 65000 коротких (!) строк, то тоже сохраняет нормально. со средней длиной строк 30 сохранил нормально, если средняя длина строк 50, то ошибку выдает. может быть влияет не длина строк, а какие-то символы в пути, пока неизвестно скопировал код из архива: я200120.xlsm.rar
Код:
Sub rrr() |
shadowbat, Происследовал затраты времени на исполнение этапов макроса. Выяснил, что накапливать очень длинную строку - это катастрофа по времени.
Вот изменённый макрос
Код:
Sub rrr() Если заархивируете и отдадите свой файл - поизмываюсь и над ним. |
Цитата:
|
megaloman,
время работы моментальное теряется одна строка, нужно заменить For i = 1 To NN на For i = 1 To NN + 1 с этим макросом плавающая ошибка №3 уже не возникает, №1 и №2 также исправлены сформировать свой файл можно через bat Код:
C: |
Время: 00:32. |
Время: 00:32.
© OSzone.net 2001-