Einzelnen Beitrag anzeigen

Benutzerbild von LoCrux
LoCrux

Registriert seit: 5. Mär 2007
Ort: Gwang-Yang-City
48 Beiträge
 
Delphi 2009 Enterprise
 
#1

Eine TCollection sortieren!

  Alt 18. Mär 2008, 10:00
Items einer TCollection sortieren!

Vielleicht ist das fuer den einen oder anderen auch interessant.
Funktioniert und getestet in Delphi 7 Enterprise.

Delphi-Quellcode:
interface {PART}

type
  
  TMyCollectionItem = CLASS(TCollectionItem)
  private
    .
    FSortIndex : Integer;
    .
  protected
    .
    .
  public
    .
    property SortIndex:Integer read FSortIndex write FSortIndex default -1;
    .
  end;


  TMyCollection = CLASS(TCollection)
  private
    .
    .
  protected
    .
    .
  public
    .
    procedure Sort;
    .
  end;


implementation {PART}

  //-----------------------------------------------------//
  // //
  //-- TCollection Hack to Access Private Declarations --//
  // //
  //-----------------------------------------------------//
  // //
  // Org. Declaration order of TCollecion in Classes //
  // //
  // TCollection = class(TPersistent) //
  // private //
  // FItemClass: TCollectionItemClass; //
  // FItems: TList; //
  // . //
  // . //
  //-----------------------------------------------------//
  // //
  // To Access eg. FItems of your TCollection //
  // //
  // SC := TShadowedCollection(Self).FItems; //
  // //
  //-----------------------------------------------------//

  {$HINTS OFF}
  TShadowedCollection = class(TPersistent)
  private
    FItemClass: TCollectionItemClass;
    FItems: TList;
  end;
  {$HINTS ON}


procedure TMyCollection.Sort;
var
  sc : TList;
  i : integer;

  procedure _QuickSort(L, R: Integer);
  var
    I, J, P : Integer;
    Save : TCollectionItem;
  begin
    repeat
      I := L;
      J := R;
      P := (L + R) shr 1;
      repeat
        while TMyCollectionItem(Items[I]).SortIndex<TMyCollectionItem(Items[P]).SortIndex do Inc(I);
        while TMyCollectionItem(Items[J]).SortIndex>TMyCollectionItem(Items[P]).SortIndex do Dec(J);
        if I <= J then begin
          Save := sc.Items[I];
          sc.Items[I] := sc.Items[J];
          sc.Items[J] := Save;
          if P = I then
            P := J
          else if P = J then
            P := I;
          Inc(I);
          Dec(J);
        end;
      until I > J;
      if L < J then _QuickSort(L, J);
      L := I;
    until I >= R;
  end;


begin
  {$WARNINGS OFF}
  if (count>1) {OTHERWISE MAKES NO SENSE}
  then begin
    //-- THE TCOLLECTION HACK TO ACCES FITMES OF THE ANCESTOR CLASS --//
    sc := TShadowedCollection(Self).FItems;
    //-- NOW CALCULATING OR DEFINIG THE SORT CRITERIA --//
    for i := 0 to sc.Count-1
      do TMyCollectionItem(sc.Items[i]).SortIndex := WhatEverToCalculateWith(sc.Items[i]); {Ein Integer Kriterium}
    //-- AND DO THE LIMBO --//
    _QuickSort(0,count-1);
  end;
  {$WARNINGS ON}
end;
WhatEver koennte z.B. ein Funktion sein aka:

Delphi-Quellcode:
 

function TMyCollection.WhatEverToCalculateWith(AItem:TCollectionItem):integer;
var
  CastedItem : TMyCollectionItem;
begin
  CastedItem := TMyCollectionItem(AItem);
  .
  .
  result := TheResultOfYourCalculation; // SORRY ABER MUSS HIER MAL ABSTRAKT BLEIBEN
end;



Alternativ geht es auch so. Hier muesst Ihr Euer Kriterium aber vorher igendwie definieren.

Delphi-Quellcode:

//-----------------------------------------------------------------//
// //
// Defined in Classes: //
// //
// TListSortCompare = function (Item1, Item2: Pointer): Integer; //
// //
//-----------------------------------------------------------------//

function compare(Item1, Item2: Pointer): Integer; {=TListSortCompare}
var v1,v2 : integer;
begin
  result := 0;
  v1 := TMyCollectionItem(Item1).SortIndex; {Oder Anderes Kriterium}
  v2 := TMyCollectionItem(Item2).SortIndex; {Oder Anderes Kriterium}
  if (v1>v2)
    then result:=1
    else if (v1<v2)
         then result := -1;
end;


procedure TMyCollection.Sort;
var
  sc : TList;

begin
  {$WARNINGS OFF}
  if (count>1) {OTHERWISE MAKES NO SENSE}
  then begin
    //-- THE TCOLLECTION HACK TO ACCES FITMES OF THE ANCESTOR CLASS --//
    sc := TShadowedCollection(Self).FItems;
    //-- AND DO THE LIMBO --//
    sc.Sort(compare); // ALTERNATIVE - BUT MAYBE MORE CALCULATIONS
  end;
  {$WARNINGS ON}
end;

{$WARNINGS ON/OFF} und {$HINTS ON/OFF} damit der Compiler nicht meckert (unsichere Typumwandlung).

Der Hack wurde so oder so aehnlich schon mal HIER AUF DELPHIPRAXIS besprochen.

Edits: Tippfehler
“C++ is an insult to the human brain.” [Niklaus Wirth]

2B OR NOT 2B (.. THAT IS FF)
  Mit Zitat antworten Zitat