Delphi-PRAXiS
Seite 2 von 5     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Sortierte TObjectList - Einträge richtig einfügen (https://www.delphipraxis.net/185916-sortierte-tobjectlist-eintraege-richtig-einfuegen.html)

stahli 17. Jul 2015 15:00

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Dann wird das ja nochmal einfacher. :thumb:
(Wobei das bezüglich Lesbarkeit für normale Menschen schon etwas gewöhnungsbedürftig ist. ;-))

Könnte man im Compare dann auch per Case dynamisch die Sortierung umstellen? Und wenn ja, müsste die komplette Liste in dem Moment auch neu durchsortiert werden - richtig?

Sir Rufo 17. Jul 2015 15:14

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Die Liste wird mit dem Comparer sortiert, wenn man
Delphi-Quellcode:
TList<T>.Sort
aufruft.

Will ich eine andere Sortierung haben, dann mit
Delphi-Quellcode:
TList<T>.Sort( AComparer: IComparer<T> )
aufrufen.

Der Comparer, den man im Konstruktor mit angibt, sorgt nicht nur für die (Standard-)Sortierung, sondern damit wird auch die Gleichheit der Elemente ermittelt.
Delphi-Quellcode:
var
  Ziel1, Ziel2, Ziel3 : TZiel;
  ZielList : TZielList;

Ziel1 := TZiel.Create; // erste Instenz
Ziel1.Wert3 := 'Foo';
Ziel2 := TZiel.Create; // zweite Instanz
Ziel2.Wert3 := 'Foo';

// Ziel1 und Ziel2 sind unterschiedliche Instanzen

ZielList := TZielList.Create;

ZielList.Add( Ziel1 );
ZielList.IndexOf( Ziel1 ); // wie zu erwarten erhält man 0
ZielList.IndexOf( Ziel2 ); // und hier? auch eine 0!!!

ZielList.Contains( Ziel1 ); // liefert true
ZielList.Contains( Ziel2 ); // liefert auch true

Ziel3 := ZielList.Extract( Ziel2 ); // welche Referenz ist jetzt in Ziel3? Ziel1, Ziel2, nil?

if Ziel3 = nil then
  ShowMessage('Ich bin leer');
if Ziel3 = Ziel2 then
  ShowMessage( 'Ich bin Ziel2' );
if Ziel3 = Ziel1 then
  ShowMessage( 'Ich bin Ziel1' );
;)

Benmik 17. Jul 2015 15:27

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Und das am Freitagnachmittag!

Was ich - unter anderem :thumb: - nicht verstehe, ist, woher der Comparer weiß, dass der beim Vergleich der Objekte "TZiel" Ziel.Wert3 vergleichen muss / soll. Ich habe mich nämlich auch schon gefragt, wie man BinarySearch verwendet, wenn man doch gar nicht die Objekte, sondern deren einzelne Werte finden will. Bei stackoverflow habe ich eine Konstruktion mit Dummy (und auch noch mit einer anonymen Methode, heute bleibt mir nichts erspart) gefunden:
Delphi-Quellcode:
function SearchList(Wert:string; Liste:TZielListe): Integer;
var Dummy : TZiel;
begin
  if not Liste.BinarySearch(Dummy, Result, TDelegatedComparer<TZiel>.Construct(
      function (const L, R: TZiel): Integer
      begin
        Result := AnsiCompareText(L.Wert3,Wert);
      end)) then
    Result := -1;
end;
Geht das auch anders?

Sir Rufo 17. Jul 2015 15:54

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Du legst doch im Comparer fest, dass mit
Delphi-Quellcode:
TZiel.Wert3
verglichen werden soll
Delphi-Quellcode:
function (const L, R: TZiel): Integer
      begin
        Result := AnsiCompareText(L.Wert3,Wert);
      end
:gruebel:

Benmik 17. Jul 2015 15:59

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Ja, in dem Dummy-Beispiel. Mit dem Dummy wird das Problem umgangen, dass auf beiden Seiten TZiel erwartet wird, während man aber TZiel.Wert3 gegen einen frei gewählten Wert vergleichen lassen will. Das Beispiel funktioniert ja auch, es ist eben nur eine Krücke. Der Compiler beschwert sich auch, dass Dummy nicht initialisiert worden sei. Daher meine Frage, ob das auch eleganter geht.

Du verwendest auch Ziel.Wert3. Ich vermute, dass die Funktionen IndexOf und Contains alle Werte von Ziel vergleichen, um Gleichheit festzustellen. Die Funktionen würden also negativ ausfallen, wenn beispielsweise Ziel.Wert2 verschieden wäre (so vermute ich).

Sir Rufo 17. Jul 2015 16:09

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Du meinst sowas hier?
Delphi-Quellcode:
uses
  Generics.Collections,
  Generics.Defaults;

type
  TZiel = class(TObject)
    WERT1 : Word;
    WERT2 : Word;
    WERT3 : String;
    WERT4 : String;
    WERT5 : Cardinal;
    WERT6 : Int64;
    WERT7 : Int64;
  end;

  TZielListe = class( TObjectList<TZiel> )
  private
    function Compare( const L,R: TZiel) : Integer;
  public
    constructor Create( OwnsObjects: Boolean = true );
    function IndexOfWert3(const Value: string) : Integer;
  end;

function TZielListe.IndexOfWert3(const Value: string) : Integer;
var
  LItem : TZiel;
begin
  LItem := TZiel.Create;
  try
    LItem.Wert3 := Value;
    if not BinarySearch( 
      LItem,
      Result,
      TComparer<TZiel>.Construct(
        function (const L, R: TZiel): Integer
        begin
          Result := AnsiCompareText( L.Wert3, R.Wert3 );
        end ) ) then
      Result := -1;
  finally
    LItem.Free;
  end;
end;

function TZielListe.Compare( const L,R: TZiel) : Integer;
begin
  Result := TComparer<string>.Default.Compare( L.Wert3, R.Wert3 );
end;

constructor TZielListe.Create( OwnsObjects: Boolean );
begin
  inherited Create( TComparer<TZiel>.Construct( Compare ), OwnsObjects );
end;
Andererseits kannst du auch den Standard-Comparer nutzen, wenn der schon passt:
Delphi-Quellcode:
function TZielListe.IndexOfWert3(const Value: string) : Integer;
var
  LItem : TZiel;
begin
  LItem := TZiel.Create;
  try
    LItem.Wert3 := Value;
    Result := IndexOf( LItem );
  finally
    LItem.Free;
  end;
end;

function TZielListe.Compare( const L,R: TZiel) : Integer;
begin
  Result := AnsiCompareText( L.Wert3, R.Wert3 );
end;

constructor TZielListe.Create( OwnsObjects: Boolean );
begin
  inherited Create( TComparer<TZiel>.Construct( Compare ), OwnsObjects );
end;

Sir Rufo 17. Jul 2015 16:16

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Ich würde das allerdings gar nicht so kompliziert gestalten.

Erzeuge dir deine Instanzen und frage die Liste, ob so eine "gleiche" Instanz schon existiert
Delphi-Quellcode:
TList<T>.Contains
. Und wenn ja, dann kannst du die Instanz einfach an die Liste anfügen und sortieren lassen.

Benmik 17. Jul 2015 16:33

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Sir Rufo, du hast es drauf.

Verstehe ich deinen Nachsatz richtig? Wenn ich ein TZiel nach einem seiner 7 Felder einsortieren lassen möchte, dann werden sowohl Contains als auch IndexOf Erfolg melden, auch wenn die anderen 6 Felder nicht übereinstimmen, sofern das Feld 3 passt, da es im Comparer angegeben ist?
Durch Angabe von verschiedenen Comparern (was ein Deutsch!) kann ich nach verschiedenen Feldern suchen und einsortieren lassen?

P.S.: Man fragt sich natürlich, ob diese Frage nicht auch durch einen Blick in den Quellcode hätte ersetzt werden können...

Sir Rufo 17. Jul 2015 16:48

AW: Sortierte TObjectList - Einträge richtig einfügen
 
So ist es ... nur dass du den Comparer nicht mehr ändern kannst ... dann musst du das mit dem BinarySearch verwenden (dort kannst du dann den gewünschten Comparer angeben).

Oder du machst es ganz anders und zwar mit einem
Delphi-Quellcode:
TFunc<T1,T2,TResult>
:
Delphi-Quellcode:
function TZielList.IndexOf<T>( AValue: T; APredicate : TFunc<T,TZiel,Boolean> ) : Integer;
var
  LIdx: Integer;
  LItem: TZiel;
begin
  for LIdx := 0 to Count - 1 do
    if APredicate( AValue, Self[LIdx] ) then
    begin
      Result := LIdx;
      Exit;
    end;
  Result := -1;
end;
und du suchst einfach nur noch mit:
Delphi-Quellcode:
ZielList.IndexOf<string>(
  'MeinWert',
  function ( Value: string; Item: TZiel ) : Boolean
  begin
    Result := AnsiCompareText( Item.Wert3, Value );
  end );

ZielList.IndexOf<Word>(
  42,
  function ( Value: Word; Item: TZiel ) : Boolean
  begin
    Result := Item.Wert1 = Value;
  end );
Ich weiß, das sieht pervers aus ... ;)

stahli 17. Jul 2015 16:58

AW: Sortierte TObjectList - Einträge richtig einfügen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1309068)
Ich weiß, das sieht pervers aus ... ;)

Endlich mal ein versöhnliches Zeichen der Einsicht! :mrgreen:

Ich gehe dann lieber immer einen verständlicheren Weg (so dass ich das dann auch nachvollziehen kann).
Wenn man solche Internas komplett versteht, hat das aber natürlich auch was. :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:46 Uhr.
Seite 2 von 5     12 34     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz