Есть много разных способов решить эту проблему. Вы показали один метод. Вы можете переключиться на виртуальный список и сохранить данные в упорядоченной структуре данных. Вы можете отсортировать список на месте.
Лично меня немного тошнит от вашего кода, который создает новый список для выполнения сортировки. И еще более тошнотворным из-за того, что вы используете текстовые представления метки времени. Если у вас большое количество элементов в списке, то виртуальный режим более эффективен.
Однако я покажу очень гибкий способ сортировки списка на месте. Начнем с кода из моего ответа здесь: https://stackoverflow.com/a/21702570/505088. Для большей самодостаточности воспроизведем приведенный здесь код, немного изменив его для использования эталонных процедур:
type
TCompareIndicesFunction = reference to function(Index1, Index2: Integer): Integer;
TExchangeIndicesProcedure = reference to procedure(Index1, Index2: Integer);
procedure QuickSort(Count: Integer; Compare: TCompareIndicesFunction;
Exchange: TExchangeIndicesProcedure);
procedure Sort(L, R: Integer);
var
I, J, P: Integer;
begin
repeat
I := L;
J := R;
P := (L+R) div 2;
repeat
while Compare(I, P)<0 do inc(I);
while Compare(J, P)>0 do dec(J);
if I<=J then
begin
if I<>J then
begin
Exchange(I, J);
//may have moved the pivot so we must remember which element it is
if P=I then
P := J
else if P=J then
P := I;
end;
inc(I);
dec(J);
end;
until I>J;
if L<J then
Sort(L, J);
L := I;
until I>=R;
end;
begin
if Count>0 then
Sort(0, Count-1);
end;
Ключевая идея здесь в том, что алгоритм сортировки отделен от хранилища данных. Именно это дает нам гибкость.
Далее нам нужно реализовать функции сравнения и обмена. Как это:
var
Compare: TCompareIndicesFunction;
Exchange: TExchangeIndicesProcedure;
Compare :=
function(Index1, Index2: Integer): Integer
var
dt1, dt2: TDateTime;
begin
dt1 := TFile.GetLastAccessTime(lb.Items[Index1]);
dt2 := TFile.GetLastAccessTime(lb.Items[Index2]);
if dt1=dt2 then begin
Result := 0;
end else if dt2<dt1 then begin
Result := -1
end else begin
Result := 1;
end;
end;
Exchange :=
procedure(Index1, Index2: Integer)
begin
lb.Items.Exchange(Index1, Index2);
end;
Обратите внимание, что я сравниваю числовое значение метки времени, что кажется гораздо более приятным. Если у меня есть порядок в обратном порядке (я всегда борюсь с функциями сравнения сортировки), тогда должно быть очевидно, как его изменить.
И, наконец, мы можем отсортировать так:
QuickSort(lb.Count, Compare, Exchange);
Этот код следует поместить внутрь вашего DescendLZB
, чтобы он мог захватывать список. Кроме того, параметр lb
не должен быть параметром var
, поскольку вы не хотите изменять его значение.
Все вместе тогда это будет выглядеть так:
procedure TBCSLBDemoC.DescendLZB(lb: TListBox);
var
Compare: TCompareIndicesFunction;
Exchange: TExchangeIndicesProcedure;
begin
Compare :=
function(Index1, Index2: Integer): Integer
var
dt1, dt2: TDateTime;
begin
dt1 := TFile.GetLastAccessTime(lb.Items[Index1]);
dt2 := TFile.GetLastAccessTime(lb.Items[Index2]);
if dt1=dt2 then begin
Result := 0;
end else if dt2<dt1 then begin
Result := -1
end else begin
Result := 1;
end;
end;
Exchange :=
procedure(Index1, Index2: Integer)
begin
lb.Items.Exchange(Index1, Index2);
end;
end;
QuickSort(lb.Count, Compare, Exchange);
end;
person
David Heffernan
schedule
30.09.2015