Поиск правильного решения

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

igordz
незнакомец
Сообщения: 6
Зарегистрирован: 12.01.2017 10:57:46

Поиск правильного решения

Сообщение igordz »

Здравствуйте, помогите найти правильный путь для решения следующующей задачи.
Просканировать все файлы в заданном каталоге (получить полный путь к файлу и дату последнего изменения) и на основе этих данных заполнить двухуровневый TreeView:
1 уровень - дата последнего изменения файла, 2 уровень - пуь и имя файла.
Сделал следующим способом: с помощью FindAllFiles получаю StringList с именами файлов и на его основе заполняю TreeView (получаю дату последнего изменения файла, ищу в TreeView узел первого уровня соответствующий дате, если есть добавляю дочерний - путь к файлу если нет, создаю узел с датой и добавляю дочерний с именем файла).
Все работает, но проблемой оказалось реализовать сортировку по дате последнего доступа. После безрезультатных попыток сортировки TreeView было принято решение построения TreeView на основе уже отсортированных данных но и тут зашел в тупик.
Есть идея на основе StringList полученого с помощью FindAllFiles построить еще один StringList методом AddObject с данными путь и имя файла и датой последнего доступа и потом его отсортировать, но признаюсь что в работе со списками "плаваю совсем мелко" поэтому и прошу помощи.
Вложения
treview2.zip
Исходники
(132.67 КБ) 554 скачивания
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

igordz писал(а):Есть идея на основе StringList полученого с помощью FindAllFiles построить еще один StringList методом AddObject с данными путь и имя файла и датой последнего доступа и потом его отсортировать

Вначале все Ваши "aDate" положите в tmpList:TStringList; затем запустите tmpList.Sort;, и только потом загружайте отсортированный список в TreeView1. И ещё сам TreeView1 даёт возможность сортировать TreeView1.Items.SortTopLevelNodes();, если ему задать алгоритм.
igordz
незнакомец
Сообщения: 6
Зарегистрирован: 12.01.2017 10:57:46

Сообщение igordz »

vitaly_l писал(а):Вначале все Ваши "aDate" положите в tmpList:TStringList; затем запустите tmpList.Sort;, и только потом загружайте отсортированный список в TreeView1


Спасибо vitaly_l, сделал на основе Вашей подсказки

Код: Выделить всё

aFiles:= TStringList.Create;
aFiles:= FindAllFiles(DirectoryEdit1.Directory, '*.*', true);
tmpList:= TStringList.Create;
for I:= 0 to aFiles.Count-1 do tmpList.AddObject(GetChangeDate(aFiles.Strings[i]), TObject(aFiles.Strings[i]));
tmpList.Sort;


Все работает, кроме сортировки, думаю что с помощью TStringList.Sort правильно отсортировать данные типа 01.12.2016, 25.08.2008 (даты) не получится, сортировка производится только по дням (по первым двум цыфрам).Результат сортировки данным способом на рисунке.

Что посоветуете насчет сортировки?
Вложения
Результат сортировки дат с помощью TStringList.Sort
Результат сортировки дат с помощью TStringList.Sort
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

igordz писал(а):с помощью TStringList.Sort правильно отсортировать данные типа 01.12.2016, 25.08.2008 (даты) не получится

Надо даты повернуть обратно: Вначале ГОД, затем МЕСЯЦ, потом ЧИСЛО - иначе любой сортировщик собьётся.
вот этот код:

Код: Выделить всё

Result:=FormatDateTime('dd.mm.yyyy', FileDateToDateTime(FileAge(aFile)));  

замените на

Код: Выделить всё

Result:=FormatDateTime('yyyy.mm.dd', FileDateToDateTime(FileAge(aFile)));  
igordz
незнакомец
Сообщения: 6
Зарегистрирован: 12.01.2017 10:57:46

Сообщение igordz »

Огромное спасибо, все получилось !
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

кстати, у всех наследников TStrings можно добавить собственную функцию сортировки
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

Снег Север писал(а):кстати, у всех наследников TStrings можно добавить собственную функцию сортировки

у TreeView оказывается, есть родная сортировка.
igordz писал(а):Огромное спасибо, все получилось !

не за что.

Я тут наткнулся, на факт, что у TreeView есть своя сортировка, если кому понадобится, она при желании позволяет сортировать как по датам так и по названиям:

Код: Выделить всё

  TreeView1.SortType:=stText;
  TreeView1.AlphaSort; 
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

чето какието сплошь неправильные решения - и даты "развернуть" и сортировать данные а не их представления в дереве.
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

zub писал(а):даты "развернуть" и сортировать данные а не их представления в дереве

Что в этом плохого? Разворот дат, наименее затратное решение. И сортировка происходит, на самом деле: представления, а не данных, т.к. сами данные вообще даже не подключаются в коде, а лишь выводятся для обозрения.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Что в этом плохого?
>>наименее затратное решение
Наименее затратное - если только по количеству серого вещества потраченого на обдумывание)) следующей хотелкой будет настройка сортировки. будем вертеть и перегружать?

>>И сортировка происходит, на самом деле: представления, а не данных
Сортируются данные перед загрузкой в контрол.

ТС, не слушай художников, художникам самим еще слушать не переслушать
Последний раз редактировалось zub 06.02.2017 20:45:55, всего редактировалось 1 раз.
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

zub писал(а):Сортируются данные

Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
zub писал(а):чудожникам самим еще слушать не переслушать

Это мы любим, излагайте, мы всё внимательно выслушаем и впитаем как губка, если наше серое вещество решит что информация будет полезна для нашего белого вещества.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
ну это ты загнул. У ТС данные это StringList который на выходе FindAllFiles.


ИМХО:
Я бы делал так:
1 - Нафиг FindAllFiles и StringList. определяем данные которые нам понадобятся и рожаем тип в котором будет полностью описывать файл, чтото типа:

Код: Выделить всё

TMyFileInfo=record
  Path,Name:String;
  CreateTime,ModifyTime:TDateTime;
  Attr:TMyFileAttr;
end;

2 - определяемся как будем организовывать массив TMyFileInfo:
2.1 - статический. сначала посчитать сколько нам понадобится элементов, потом выделить в памяти нужный объем данных и заполнять
2.2 - динамический. тут главное будет организовать обертку над динмассивом, чтоб добавлять элементы не по одному а "небольшими пачками"
2.3 - использовать готовую обертку над 2.2, например GVector из fcl-stl
Мне ближе вариант 2.3

3 - на основе FindFirst\FindNext заполнить массив из 2. Это наши данные, мы их получили и храним.

Далее определяемся с котролом. ХЗ что из себя представляет TreeView, но думаю (уверен) в нем можно организовать овнердрав и привязать внешние данные к узлам. Создаем узлы и привязываем к ним инфу в виде индекса в нашем массиве данных или непосредственно указателя на данные. Овнердрав процедура отображает имя ноды на основе данных взятых по индексу\указателю в соответствии с настройками, процедура сортировки сортирует ноды на основе данных взятых по индексу\указателю на основе настройки способа сортировки. Настройки отображения\сортировки можно менять налету без пересоздания дерева.
Возможно вместо TreeView больше подойдет VirtualTree
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

zub писал(а):привязываем к ним инфу в виде индекса в нашем массиве данных или непосредственно указателя на данные

Не знаю как ТС, но серо-художественное вещество передаёт замечательно полученную инфу, в бело-художественный отдел. Информация, оказалась ОЧЕНЬ кстати, в смысле актуальной на все 100500, т.к. я сейчас решаю именно эту задачу (дорога ложка к обеду). И хотел было привязывать имена файлов, но предложенная схема нравится больше, т.к. потом, можно будет это использовать как дополнительно-удобный сервис. Художественное спасибо за офигенно полезный ликбез! :roll: Хорошего всем настроения! :wink:

.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>но предложенная схема нравится больше
Ждем тему про непонятный вылет при закрытии и забагованость canclose))
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

zub писал(а):>>Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
Я бы делал так:
1 - Нафиг FindAllFiles и StringList. определяем данные которые нам понадобятся и рожаем тип в котором будет полностью описывать файл, чтото типа:

Код: Выделить всё

TMyFileInfo=record
  Path,Name:String;
  CreateTime,ModifyTime:TDateTime;
  Attr:TMyFileAttr;
end;


Это наши данные, мы их получили и храним.

Возможно вместо TreeView больше подойдет VirtualTree

VT просто напрашивается.
Там и с хранением данных, и с сортировкой, и с внешним видом данных - всё замечательно.
Ответить