Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Record Verwalten - Wie am besten ? (https://www.delphipraxis.net/160210-record-verwalten-wie-am-besten.html)

turboPASCAL 2. Mai 2011 19:22

Record Verwalten - Wie am besten ?
 
Hi,

ich mochte einen/mehrere Record(s) verwalten. Ich habe das jetzt mit einem dyn. Array gelöst,
was mir aber nicht so gefällt. Ich habe da an TList gedacht komme aber nicht so recht voran.

Ich möcht in der Liste auf den Record über einen Index, was ja nun eion Problem ist, aber auch
über einen Namen zugreifen können und da fällt mir nix ein...

Pseudocode
Code:
type
  myRecord = record
    Handle: int
    Titel: string
  end;

type
  myRecordList = List of myRecord


begin
  myRecordList.add(Handle1, 'Abc');
  myRecordList.add(Handle2, 'Def');
  myRecordList.add(Handle3, 'Ghi');

 
  // holen per List-Index //
  anyHandle := myRecordList[Idx].Handle
  anyTitel := myRecordList[Idx].Titel

  // holen per List-Index //
  anyHandle := myRecordList.GetFromTitle('Abc').Handle

  // Löschen
  myRecordList[Idx].Delete;
  myRecordList[ myRecordList.GetFromTitle('Abc').Index ].Delete;
end.


So eine (fasst) fertige oder ähnliche Klasse gibt es nicht in Delphi gelle ?

BUG 2. Mai 2011 19:28

AW: Record Verwalten - Wie am besten ?
 
Klingt irgendwie nach einem Dictionary, besonders wenn du denn Index nur zum Durchlaufen brauchst.

patti 2. Mai 2011 19:28

AW: Record Verwalten - Wie am besten ?
 
Hm, spontan würde mir da ein Assoziatives Array oder eine Hashtable einfallen, allerdings kenn ich keine Implementierungen dafür in Delphi und ich weiß auch nicht, ob man dann zusätzlich zum Schlüssel auch noch per Index auf die einzelnen Elemente zugreifen kann...

Edit: BUG war mit seinem Dictionary schneller. Das scheint alle Anforderungen zu erfüllen - und baut auf dem Hashtable-Prinzip auf ;)

turboPASCAL 2. Mai 2011 20:46

AW: Record Verwalten - Wie am besten ?
 
Hm, so etwas "fettes" wollt ich ja nun nicht.

Ich muss mal sehen ob man da was von TStringlist o.ä. ableiten kann.

BUG 2. Mai 2011 20:54

AW: Record Verwalten - Wie am besten ?
 
Evtl. ist funktioniert Objects in TStringList.

brechi 2. Mai 2011 20:59

AW: Record Verwalten - Wie am besten ?
 
Für String und Integer kann man wirklich eine TStringList mit Objects missbrauchen
AddObject('test', Pointer(1234));

BUG 2. Mai 2011 21:35

AW: Record Verwalten - Wie am besten ?
 
Zitat:

Zitat von brechi (Beitrag 1098444)
Für String und Integer kann man wirklich eine TStringList mit Objects missbrauchen
AddObject('test', Pointer(1234));

Oder eben Zeiger auf Records :mrgreen:

brechi 2. Mai 2011 21:38

AW: Record Verwalten - Wie am besten ?
 
Dann muss man die Records aber selber wieder verwalten (dyn Array etc.) insbesondere beim loaeschen einzelner Items. Dann doch lieber eine eigene Klasse mit TObjectList ;)

dataspider 2. Mai 2011 22:51

AW: Record Verwalten - Wie am besten ?
 
Hi,

dafür bietet sich ein Array Property an.
Allerdings würde ich das auch über eine Klasse lösen, ungefähr so:
Delphi-Quellcode:
unit MyClasses;

interface

uses
  Contnrs, SysUtils;

type
  TItem = class(TObject)
  private
    FTitel: string;
    FHandle: Integer;
  public
    property Titel: string read FTitel write FTitel;
    property Handle: Integer read FHandle write FHandle;
  end;

type
  TItemList = class(TObject)
  private
    FItems: TObjectList;
    function GetItems(Index: Integer): TItem;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add(const ATitel: string; AHandle: Integer);
    procedure Clear;
    function Count: Integer;
    function ItemByName(AName: string): TItem;
    property Items[Index: Integer]: TItem read GetItems;
  end;

implementation

constructor TItemList.Create;
begin
  inherited;
  FItems := TObjectList.Create(True);
end;

destructor TItemList.Destroy;
begin
  FItems.Free;
  inherited Destroy;
end;

procedure TItemList.Add(const ATitel: string; AHandle: Integer);
Var
  AItem: TItem;
begin
  AItem := TItem.Create;
  AItem.Titel := ATitel;
  AItem.Handle := AHandle;
  FItems.Add(AItem);
end;

procedure TItemList.Clear;
begin
  FItems.Clear;
end;

function TItemList.Count: Integer;
begin
  Result := FItems.Count;
end;

function TItemList.GetItems(Index: Integer): TItem;
begin
  Result := TItem(FItems[Index]);
end;

function TItemList.ItemByName(AName: string): TItem;
Var
  i: Integer;
begin
  Result := nil;
  for i := 0 to Count - 1 do
  if SameText(FItems[i], AName) then
  begin
    Result := Items[i];
    Exit;
  end;
end;

end.
Ich glaube nur, dass Delphi 6 noch keine TObjectList hatte, oder?
Dann muss natürlich ein TList herhalten, und beim Delete und Clear die Freigabe des Objektes mit erfolgen.

Frank

Aphton 2. Mai 2011 23:09

AW: Record Verwalten - Wie am besten ?
 
Ich weiß nicht, wie die Methode heißt, die ich gleich vorschlagen werde; ich vermute, es ist das, was bei Post #3 angesprochen wurde und zwar Hashtable. Falls es das ist, dann tut mir die Redundanz Leid :P

Du legst ein Array fester Größe an und schreibst dir eine Hashfunktion, die einen Maximalwert = Größe des Arrays zurückliefert. Beispiel:
Delphi-Quellcode:
MeinArray: Array[0..255] of ...;
funciton MyHashFunc(const Str: String): Byte; // liefert 0..255 zurück
Der Hash gibt den Index zum Array.

Wenn ich zb. 'ABC' habe und der Hash davon 1 ist, dann habe ich folgendes:
Code:
MeinArray[1] = 'ABC'
So, wenn nun ein weiteres Element, 'BCD', denselben Hash, 1, zurückliefert, dann füge ich es hinzu.
Code:
MeinArray[1].Next = 'BCD'
Dazu müsste man einfach eine einfach-verkettete Liste als Element verwenden.

Und wenn man nun ein Element (schnell) suchen möchte, berechnet man den Hash davon, schaut im Array nach, welches Element der Liste es ist und liefert es dann halt als Ergebnis zurück

Edit: Beim nochmaligen Lesen ist mir aufgefallen, dass du Arrays meiden möchtest.
Mit dieser Methode hier wird es aber leichter und effizienter, nach Strings zu suchen.
Falls es trotzdem nicht so das Wahre ist, dann macht das auch nichts :P

dataspider 3. Mai 2011 09:50

AW: Record Verwalten - Wie am besten ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
bei einer RecordList musst du dich IMHO um den Speicher kümmern.
Ich habe mal ein Beispiel angehangen.

Frank

himitsu 3. Mai 2011 10:05

AW: Record Verwalten - Wie am besten ?
 
Zitat:

Zitat von dataspider (Beitrag 1098504)
bei einer RecordList musst du dich IMHO um den Speicher kümmern.
Ich habe mal ein Beispiel angehangen.

Frank

Zum Glück gibt es inzwischen (seit D2009) auch noch die generische TList<>, welche da vieles vereinfacht. :angle2:
(auch wenn dieses eine kleine und manchmal gemeine Einschränkung besitzt, was das nachträgliche Ändern eines Recordinhaltes betrifft :wall: )

Und was den Ausgangsrecord dieses Threads betrifft:
Delphi-Quellcode:
TDictionary<Handle, String>
, mit Handle als Key und String als Value (oder andersrum).

taveuni 3. Mai 2011 10:40

AW: Record Verwalten - Wie am besten ?
 
Der Vollständigkeit halber noch die sich an Bord befindende
THashedStringlist.

Elvis 3. Mai 2011 10:55

AW: Record Verwalten - Wie am besten ?
 
Zitat:

Zitat von BUG (Beitrag 1098434)
Klingt irgendwie nach einem Dictionary, besonders wenn du denn Index nur zum Durchlaufen brauchst.

+1
Alzaimars Klassen sind alles andere als "fett". Wer seine Beiträge kennt, weiß wie wichtig ihm Performance ist.
Und seine kleinen Hashlisten sind mehr zackig genug. Wenn du Zugriff zu neueren Delphis hast, kannsu dir TDictionary<int, String> ankieken.
Bis dahin ist sein TIntegerDictionary so ziemlich das wassu willst.
Zitat:

Zitat von himitsu (Beitrag 1098511)
Zum Glück gibt es inzwischen (seit D2009) auch noch die generische TList<>, welche da vieles vereinfacht. :angle2:
(auch wenn dieses eine kleine und manchmal gemeine Einschränkung besitzt, was das nachträgliche Ändern eines Recordinhaltes betrifft :wall: )

Records sind Werte, keine Objekte und erst recht keine "Entitäten". Und in fast jedem Fall sollten Werte unveränderlich sein. Will heißen, dass eine Änderung eine veränderte Kopie liefern sollte. Nur so ist klar was unter der Haube tatsächlich passiert.

Delphi-Quellcode:
var x, y TDeinRecord;
begin
  x.Abc := 1;
  y := x;
  x.Abc := 2
  Assert(y.Abc = 2, 'Ja y.Abc = 1, denn y hat bekam ja auch eine KOPIE, so arbeiten reine *Werte* nunmal.');
end;
http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil
Wer Records als Objekte missbraucht, weil er keinen Bock auf Speicherverwaltung hat, hat die falsche Laufzeitumgebung gewählt.

shmia 3. Mai 2011 13:00

AW: Record Verwalten - Wie am besten ?
 
Nochmals Entscheidungshilfe Record vs. Klasse innerhalb von Listen

Record
* bei sehr einfachen Strukturen wie z.B. TPoint oder Vektoren die in hoher Anzahl
(z.B. 3D Gittermodell) benötigt werden
Records benötigen geringfügig weniger Speicherplatz (4Bytes) als Objekte, was bei Stückzahlen im Millionenbereich eine Rolle spielen kann
* bei Records die von Aussen vorgegeben fest werden (z.B. Records der Windows API, Records einer Datei)

Klasse
* der Standardweg ist, dass man Datenstrukturen als Klassen abbildet
* die Klassen sollten nicht nur Properties haben, sondern auch Methoden, die mit den Daten arbeiten
* Programme, die mit Arrays oder Listen von Records arbeiten, verwenden implizit auch Code, der mit den Daten des Records arbeitet.
Nur ist dieser Code unkontrolliert in der Anwendung verschmiert, während bei einer Klasse der Code in Methoden klar erkennbar (und testbar!) wird.

==> In 95% der Fälle wird man sich für eine Klasse als Datenkontainer entscheiden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:52 Uhr.

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