AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Sortierte TObjectList - Einträge richtig einfügen

Sortierte TObjectList - Einträge richtig einfügen

Ein Thema von Benmik · begonnen am 17. Jul 2015 · letzter Beitrag vom 24. Sep 2015
Antwort Antwort
Seite 2 von 5     12 34     Letzte » 
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.284 Beiträge
 
Delphi 10.4 Sydney
 
#11

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

  Alt 17. Jul 2015, 15:00
Dann wird das ja nochmal einfacher.
(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?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#12

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

  Alt 17. Jul 2015, 15:14
Die Liste wird mit dem Comparer sortiert, wenn man TList<T>.Sort aufruft.

Will ich eine andere Sortierung haben, dann mit 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' );
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (17. Jul 2015 um 15:16 Uhr)
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
486 Beiträge
 
Delphi 10.4 Sydney
 
#13

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

  Alt 17. Jul 2015, 15:27
Und das am Freitagnachmittag!

Was ich - unter anderem - 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?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#14

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

  Alt 17. Jul 2015, 15:54
Du legst doch im Comparer fest, dass mit TZiel.Wert3 verglichen werden soll
Delphi-Quellcode:
function (const L, R: TZiel): Integer
      begin
        Result := AnsiCompareText(L.Wert3,Wert);
      end
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
486 Beiträge
 
Delphi 10.4 Sydney
 
#15

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

  Alt 17. Jul 2015, 15:59
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).

Geändert von Benmik (17. Jul 2015 um 16:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#16

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

  Alt 17. Jul 2015, 16:09
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;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (17. Jul 2015 um 16:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

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

  Alt 17. Jul 2015, 16:16
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 TList<T>.Contains . Und wenn ja, dann kannst du die Instanz einfach an die Liste anfügen und sortieren lassen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
486 Beiträge
 
Delphi 10.4 Sydney
 
#18

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

  Alt 17. Jul 2015, 16:33
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...

Geändert von Benmik (17. Jul 2015 um 16:43 Uhr) Grund: Selbsterkenntnis
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#19

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

  Alt 17. Jul 2015, 16:48
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 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 ...
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.284 Beiträge
 
Delphi 10.4 Sydney
 
#20

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

  Alt 17. Jul 2015, 16:58
Ich weiß, das sieht pervers aus ...
Endlich mal ein versöhnliches Zeichen der Einsicht!

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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf