![]() |
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? |
AW: Sortierte TObjectList - Einträge richtig einfügen
Die Liste wird mit dem Comparer sortiert, wenn man
Delphi-Quellcode:
aufruft.
TList<T>.Sort
Will ich eine andere Sortierung haben, dann mit
Delphi-Quellcode:
aufrufen.
TList<T>.Sort( AComparer: IComparer<T> )
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' ); |
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:
Geht das auch anders?
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; |
AW: Sortierte TObjectList - Einträge richtig einfügen
Du legst doch im Comparer fest, dass mit
Delphi-Quellcode:
verglichen werden soll
TZiel.Wert3
Delphi-Quellcode:
:gruebel:
function (const L, R: TZiel): Integer
begin Result := AnsiCompareText(L.Wert3,Wert); end |
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). |
AW: Sortierte TObjectList - Einträge richtig einfügen
Du meinst sowas hier?
Delphi-Quellcode:
Andererseits kannst du auch den Standard-Comparer nutzen, wenn der schon passt:
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;
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; |
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:
. Und wenn ja, dann kannst du die Instanz einfach an die Liste anfügen und sortieren lassen.
TList<T>.Contains
|
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... |
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:
und du suchst einfach nur noch mit:
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;
Delphi-Quellcode:
Ich weiß, das sieht pervers aus ... ;)
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 ); |
AW: Sortierte TObjectList - Einträge richtig einfügen
Zitat:
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 22:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz