2015-09-30 74 views
1

我在回顧一些關於如何按降序對列表框項進行排序的問題。似乎默認和唯一的順序是升序。我們確實有可用的字符串集合(TStringList)。降序列表框項目Delphi XE8

在我看來,如果我們插入排序目標集合列表中,執行排序(升序),但訪問降序排序的項,並將它們添加到未排序列表框項目的關鍵是剝離後關閉,我們收到了期望的下降效果。

procedure TBCSLBDemoC.DescendLZB(var lb: TListBox); 
var 
    sc: TStringList; 
    i: Integer; 
    rdt: TDateTime; 
    buf : string; 
begin 
    sc := TStringList.Create; 
    i := 0; 
    repeat 
    rdt := TFile.GetLastAccessTime(lb.Items[i]); 
    sc.Add(FormatDateTime('YYYYMMDDHHMMSS', rdt) + ' ' + lb.Items[i]); 
    Inc(i); 
    until (i > (lb.Count - 1)); 
    sc.Sort; 
    lb.Sorted := false; 
    lb.Items.Clear; 
    i := sc.Count - 1; 
    repeat 
    buf := sc[i]; 
    Delete(buf, 1, 15); 
    lb.Items.Add(buf); 
    dec(i); 
    until (i < 0); 
    sc.Free; 
end; 

這些結果似乎對我很好,但我的問題是我將如何改進這種技術?我相信我忽略了一些東西。,

回答

3

有很多不同的方法可以解決這個問題。你已經展示了一種方法。您可以切換到虛擬列表框並將數據存儲在您訂購的數據結構中。你可以就地排序列表。

就我個人而言,我覺得有點que looking不安,看着你的代碼創建一個新的列表來執行排序。而且,通過使用時間戳的文本表示,更加令人不安。如果列表中有大量項目,則虛擬模式更有效。

但是,我將演示一種非常靈活的方式來就地排序列表。讓我們從我的答案中的代碼開始: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;