AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi "Array" mit Strings als Indizes (Zuordnungstabelle)
Thema durchsuchen
Ansicht
Themen-Optionen

"Array" mit Strings als Indizes (Zuordnungstabelle)

Ein Thema von blackdrake · begonnen am 15. Mär 2009 · letzter Beitrag vom 27. Mär 2009
Antwort Antwort
Seite 2 von 2     12   
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#11

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 17. Mär 2009, 21:08
Zitat von Cyf:
Ok, das ist jetzt ein Wrapper für eine Klasse mit ein paar extra Methoden, um nicht jedesmal den Index mit den Funktionen dafür zu ermitteln, sondern das direkt da rein zu bauen?
Mh, hat zum einen damit zu tun, dass ich ursprünglich was eigenes gebaut hatte und die List-Möglichkeit nicht kannte, zum anderen dass ich meine Implementierung bei behalten will. Aber es hat auch was gutes: Wenn man mit dieser Wrapper-Klasse arbeitet, muss man sich nicht darum kümmern, wie die Liste eigentlich aufgebaut ist, sondern greift darauf zu wie eine INI-Datei.

Zitat von Cyf:
Nebenbei sind auch die Abfragen, ob Einträge existieren unschön, entweder sie sollten dann angelegt werden, oder bei Abfragen sollte eine Exception geworfen werden, um zu signaliesieren, dass es den Eintrag nicht gibt, weil man nil ja auch zuweißen könnte.
In der Allgemeinen Lösung ja, aber ich brauche nur zu wissen, ob es nil ist oder nicht. nil oder nicht-vorhanden macht mir persönlich nichts aus.

Zitat von Cyf:
Ich nicht, sowas sollte in eine Property.
Meiner Ansicht nach ist es schlecht, das Case-Sensitive mittendrin zu ändern. Dann gehen nämlich zum einen Einträge verloren, zum Anderen werden Einträge, die vorher existiert haben, plötzlich als nicht vorhanden gekennzeichnet. Ich bin der Meinung, das sollte man vorher exakt definieren. Ich muss ja im Allgemeinen beim Createn eines Objektes ja auch genau wissen, was ich denn erstellen will und kann mich dann auch nicht mehr umentscheiden.
Daniel Marschall
  Mit Zitat antworten Zitat
Cyf

Registriert seit: 30. Mai 2008
407 Beiträge
 
Lazarus
 
#12

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 17. Mär 2009, 23:07
Zitat von blackdrake:
Meiner Ansicht nach ist es schlecht, das Case-Sensitive mittendrin zu ändern. Dann gehen nämlich zum einen Einträge verloren, zum Anderen werden Einträge, die vorher existiert haben, plötzlich als nicht vorhanden gekennzeichnet. Ich bin der Meinung, das sollte man vorher exakt definieren. Ich muss ja im Allgemeinen beim Createn eines Objektes ja auch genau wissen, was ich denn erstellen will und kann mich dann auch nicht mehr umentscheiden.
Ich kann nicht nachvollziehen, warum Einträge verloren gehen sollen, natürlich werden kleingeschriebene Einträge dann nicht mehr mit einem großgeschriebenen Suchbegriff gefunden, aber das ist ja der Sinn der Sache und sollten weitere Anpassungen nötig sein, kannst du diese mit einer Methode hinter der Property durchführen. Der Sinn von Klasssen und OOP ist, sie so allgemein zu halten, dass sie wiederverwendbar sind und nicht nur für einen speziellen Anwendungsfall zu gebrauchen. Aber ist ja deine Klasse.
Aus dem selben Grund finde ich auch Ableiten hier geschickter als einen Wrapper: Man verliert nicht den Zugriff auf die alten Funktionen, sondern erreicht deine neuen nur zusätzlich und bleibt kompatibel zu Prozeduren, die die Vorfahren erwarten.
Man kann einen Barbier definieren als einen, der alle diejenigen rasiert, und nur diejenigen, die sich nicht selbst rasieren.
Rasiert sich der Barbier?
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#13

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 17. Mär 2009, 23:14
Zitat von Cyf:
Ich kann nicht nachvollziehen, warum Einträge verloren gehen sollen
Ich hatte bei einem Test herausgefunden, dass wenn man z.B. "abc" zuweist, dann "ABC" zuweist, dann C.S. ausschaltet und dann auf "abc" zugreift, man eigentlich "ABC" erhält. Dieses Verschweißen der Einträge finde ich äußerst ungeschickt, denn das wäre wie wenn man Müll zuerst sortieren und dann in eine Tonne schütten würde, nur dass hier eben ein Verlust an Einträgen besteht. Ist das C.S. vorher definiert, kann explizit das Überschreiben und Neuanlegen durch die eigene Klasse kontrolliert werden. Deswegen habe ich lieber einen Wrapper gemacht als eine Ableitung.

Ja, im Allgemeinen Fall wäre eine Ableitung besser. Eben mit den einfachereren Funktionen als Zusatz.
Daniel Marschall
  Mit Zitat antworten Zitat
Cyf

Registriert seit: 30. Mai 2008
407 Beiträge
 
Lazarus
 
#14

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 17. Mär 2009, 23:24
Das gleichlautende Einträge beim Abschalten kollidieren ist natürlich wahr, den Fall müsste man in der Tat berücksichtigen und überlegen, welcher in der Liste bleiben darf und ob dies ggf. irgendwie kenntlich gemacht wird (Exception, Message).
Man kann einen Barbier definieren als einen, der alle diejenigen rasiert, und nur diejenigen, die sich nicht selbst rasieren.
Rasiert sich der Barbier?
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#15

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 18. Mär 2009, 01:51
Kennst du schon die Array-Properties?
Damit kann man die Sache sehr elegant lösen:
Delphi-Quellcode:
TEasyObjectManager = class(TObject)
private
  function GetValues(const Name: string): TObject;
  procedure SetValues(const Name: string; Value: TObject);
public
  ...
  // das ist ein Array-Property
  // interessant ist, das der Datentyp des Index auch string oder ein beliebiger anderer Datentyp sein darf
  // auch mehrdimensionale Indizes sind möglich
  property Values[const Name:string]:TObject read GetValues write SetValue;
end;
Ein bekanntes Array-Property ist z.B. Pixel[] der Klasse TCanvas.
Die Deklaration sieht ungefähr so aus:
property Pixel[x,y:Integer]:TColor read GetPixel write SetPixel; Wenn man unsicher ist, wie die Get- und Set-Methoden aussehen sollen, dann schreibt
das Array-Property einfach hin und drückt dann Strg+Shift+C und die IDE erzeugt dann automatisch die richtigen Methodenkörper.
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#16

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 18. Mär 2009, 07:57
Das ist ja was tolles! Vielen Dank für den Hinweis, da komm ich ja dem PHP-Fealing noch näher. Werde ich später gleich mal ausprobieren.
Daniel Marschall
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#17

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 23. Mär 2009, 11:17
Hallo.

Ich bin jetzt zum entschluss gekommen, folgende Dinge zu machen:
1. Klasse von TStringList ableiten anstelle eines Wrappers
2. Exception werfen, wenn Eintrag nicht existiert anstelle nil zu liefern.

Bezüglich (1) möchte ich aber folgende Funktionweise: Es soll eine Exception geworfen werden, wenn durch das Ändern von Case-Sensitive Einträge miteinander "verschmelzen" (bzw. genau genommen danach nicht mehr durch ObjectByString[str] nicht mehr zugreifbar sind).

Dazu habe ich eine kleine Frage bevor ich meinen Code hier veröffentliche: Wie prüfe ich performant, ob bei einer CaseSensitive=False Änderung Einträge "verschmelzen" werden?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#18

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 27. Mär 2009, 09:50
OK, hier nun mein fertiger Code:

Delphi-Quellcode:
unit ObjMan;

interface

uses
  SysUtils, IniFiles;

type
  TObjectManager = class(THashedStringList)
  private
    function GetObjectByString(const Str: String): TObject;
    procedure SetObjectByString(const Str: String; const Value: TObject);
    function GetStringByObject(const Obj: TObject): String;
    procedure SetStringByObject(const Obj: TObject; const Value: String);
  public
    function StringExists(const Str: String): boolean;
    function ObjectExists(const Obj: TObject): boolean;
    function DeleteString(const Str: String): boolean;
    property ObjectByString[const Str: string]: TObject
      read GetObjectByString write SetObjectByString;
    property StringByObject[const Obj: TObject]: String
      read GetStringByObject write SetStringByObject;
  end;

  EStringNotFound = class(Exception);
  EObjectNotFound = class(Exception);

resourcestring
  E_STRING_NOT_FOUND = 'The string "%s" was not found in the list.';
  E_OBJECT_NOT_FOUND = 'Object was not found in the list.';

implementation

{ TObjectManager } 

function TObjectManager.GetObjectByString(const Str: string): TObject;
var
  i: integer;
begin
  i := IndexOf(Str);
  if i <> -1 then
    result := Objects[i]
  else
    raise EStringNotFound.CreateFmt(E_STRING_NOT_FOUND, [Str]);
end;

procedure TObjectManager.SetObjectByString(const Str: string;
  const Value: TObject);
var
  i: integer;
begin
  i := IndexOf(Str);
  if i <> -1 then
    Objects[i] := Value
  else
    AddObject(Str, Value);
end;

function TObjectManager.StringExists(const Str: string): boolean;
begin
  result := IndexOf(Str) <> -1;
end;

function TObjectManager.ObjectExists(const Obj: TObject): boolean;
begin
  result := IndexOfObject(Obj) <> -1;
end;

function TObjectManager.DeleteString(const Str: string): boolean;
var
  i: integer;
begin
  i := IndexOf(Str);
  result := i <> -1;
  if result then Delete(i);
end;

function TObjectManager.GetStringByObject(const Obj: TObject): String;
var
  i: integer;
begin
  i := IndexOfObject(Obj);
  if i <> -1 then
    result := Strings[i]
  else
    raise EObjectNotFound.Create(E_OBJECT_NOT_FOUND);
end;

procedure TObjectManager.SetStringByObject(const Obj: TObject;
  const Value: String);
var
  i: integer;
begin
  i := IndexOfObject(Obj);
  if i <> -1 then
    Strings[i] := Value
  else
    AddObject(Value, Obj);
end;

end.
Die Exceptions bei "Verschmelzung" von Einträgen habe ich doch nicht gemacht, da ein solches Verhalten nicht nur durch Case-Sensitive entstehen kann, sondern auch, wenn man einfach zwei Einträge mit identischen Strings hinzufügt. Wenn man aber Konsequent nur mit ObjectByString[] arbeitet, kommt es zu keiner Überdeckung.

Man beachte bitte das dynamische Verhalten von SetStringByObject() und SetObjectByString(). Diese fügen einen neuen Eintrag hinzu, wenn man auf ein unbekanntes Element schreibend zugreift.

Gruß
blackdrake
Angehängte Dateien
Dateityp: pas objman_949.pas (2,4 KB, 1x aufgerufen)
Daniel Marschall
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#19

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 27. Mär 2009, 11:11
ich spiel auch mal ein bissl mit ... nja, zumindestens das "Array" funktioniert schonmal
Delphi-Quellcode:
Uses Types, SysConst, SysUtils;

Type TMyType = Integer;
  TMyStringIndizeInnerArray = Array of Record
    Name: String;
    Data: TMyType;
  End;
  TMyStringIndizeArray = Record
  Private
    _A: TMyStringIndizeInnerArray;
    Procedure SetData(Const Name: String; Const Data: TMyType);
    Function GetData(Const Name: String): TMyType;
    Procedure SetDataI( Index: Integer; Const Data: TMyType);
    Function GetDataI( Index: Integer): TMyType;
    Function GetName ( Index: Integer): String;
  Public
    Class Operator Implicit(Const A: TMyStringIndizeInnerArray): TMyStringIndizeArray;
    Class Operator Implicit(Const Rec: TMyStringIndizeArray): TMyStringIndizeInnerArray;
    Property Data[Const Name: String]: TMyType Read GetData Write SetData; Default;
    Property Data[ Index: Integer]: TMyType Read GetDataI Write SetDataI; Default;
    Property Name[ Index: Integer]: String Read GetName;
  End;

Procedure TMyStringIndizeArray.SetData(Const Name: String; Const Data: TMyType);
  Var i: Integer;

  Begin
    i := 0;
    While (i < Length(_A)) and (_A[i].Name <> Name) do Inc(i);
    If (i >= Length(_A)) Then Begin
      SetLength(_A, i + 1);
      _A[i].Name := Name;
    End;
    _A[i].Data := Data;
  End;

Function TMyStringIndizeArray.GetData(Const Name: String): TMyType;
  Var i: Integer;

  Begin
    i := High(_A);
    While _A[i].Name <> Name do Dec(i);
    Result := GetDataI(i);
  End;

Procedure TMyStringIndizeArray.SetDataI(Index: Integer; Const Data: TMyType);
  Begin
    If (Index >= 0) and (Index < Length(_A)) Then _A[Index].Data := Data
    Else Raise ERangeError.CreateRes(@SRangeError);
  End;

Function TMyStringIndizeArray.GetDataI(Index: Integer): TMyType;
  Begin
    If (Index >= 0) and (Index < Length(_A)) Then Result := _A[Index].Data
    Else Raise ERangeError.CreateRes(@SRangeError);
  End;

Function TMyStringIndizeArray.GetName(Index: Integer): String;
  Begin
    If (Index >= 0) and (Index < Length(_A)) Then Begin
      If _A[Index].Name <> 'Then Result := _A[Index].Name
      Else Result := IntToStr(Index);
    End Else Raise ERangeError.CreateRes(@SRangeError);
  End;

Class Operator TMyStringIndizeArray.Implicit(Const A: TMyStringIndizeInnerArray): TMyStringIndizeArray;
  Begin
    Result._A := A;
  End;

Class Operator TMyStringIndizeArray.Implicit(Const Rec: TMyStringIndizeArray): TMyStringIndizeInnerArray;
  Begin
    Result := Rec._A;
  End;


procedure TForm1.FormCreate(Sender: TObject);
Var A: TMyStringIndizeArray;

Begin
  //SetLength(A, 5); // geht leider doch nicht ... blöder Var-Parameter -.-°
  A['himi'] := 0815;
  If A['himi'] = A[0] Then ;
  If Length(A) = 1 Then ; // aber warum geht das auch nicht? o.O
End;
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#20

Re: "Array" mit Strings als Indizes (Zuordnungstab

  Alt 27. Mär 2009, 12:08
Sieht nett aus

[OT]
Ich benutze in so einer Situation aber eher Dictionary<TKey, TValue> bzw. im speziellen dann Dictionary<String, int>

SCNR
[/OT]
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 14:55 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