AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Mehrdimensionale Variable variabler Dimension
Thema durchsuchen
Ansicht
Themen-Optionen

Mehrdimensionale Variable variabler Dimension

Ein Thema von Whookie · begonnen am 9. Okt 2014 · letzter Beitrag vom 12. Okt 2014
Antwort Antwort
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
445 Beiträge
 
Delphi 10.3 Rio
 
#1

Mehrdimensionale Variable variabler Dimension

  Alt 9. Okt 2014, 23:54
Delphi-Version: XE5
Bin gerade dabei eine Klasse zu bauen, mit der zur Laufzeit ein Variable angelegt werden kann, die ein Array beliebiger Dimension (0-3) eines bestimmten Types enthalten kann (Boolean, Double, Integer, AnsiString, ...).

Im Prinzip bin ich bei sowas gelandet:

Delphi-Quellcode:
  
TDimArray = Array Of Integer;

TVariable<T> = Class
  private
    fDimensions: TDimArray;
    fPData: PByte;
    fMemSize: Integer;
  public
    constructor Create(AName: AnsiString; const ADimensions: TDimArray); virtual;

    property Value[Index: TDimArray]: T read GetVal write SetVal;
 End;
Was daran natürlich nicht so elegant ist, sind die Zugriffe über Value, bei denen ich mir nicht sicher bin ob sie von der Performance her so günstig sind:

Delphi-Quellcode:
Var
  x: TVariable<Integer>;
begin
  x := TVariable<Integer>.Create('Test', [2,3,9]);
  x.Value[[0,0,2]] := 16
  ...
Verwaltet werden die Daten in einem großen Speicherblock (fPData) weil keinen Weg gefunden habe eine Mehrdimensionale Variable variabler Dimension zu definieren (geht sowas überhaupt??).

Statt der Value- Property wären auch einzelne entsprechend dimensionierte Properties denkbar:

Delphi-Quellcode:
    property Value1D[Index: Integer]: T read GetValue1D write SetValue1D;
    property Value2D[x, y: Integer]: T read GetValue2D write SetValue2D;
    property Value3D[x, y, z: Integer]: T read GetValue3D write SetValue3D;
Ist möglicherweise schneller aber nicht besonders elegant. Gibts hier eine Möglichkeit einfach die "richtige" property anzulegen zb. über Generics?
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Mehrdimensionale Variable variabler Dimension

  Alt 10. Okt 2014, 09:38
Bei den Generics kann man nur veränderliche Typen deklarieren, aber die Anzahl bleibt immer gleich.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#3

AW: Mehrdimensionale Variable variabler Dimension

  Alt 10. Okt 2014, 21:14
etwas um die Ecke gedacht realisiert man das z.B. intern als Hash mit einem Key, welcher sich eben aus den verketteten "beliebigen Dimensionen" zusammen setzt.

Nehmen wir als Beispiel das ganze als StringHash:

setzen: sh.Add(IntToStr(x)+'-'+IntToStr(y)+'-'+IntToStr(z), stringvalue)
lesen: stringvalue := sh.Get(IntToStr(x)+'-'+IntToStr(y)+'-'+IntToStr(z));

Das ist vom Speicherplatz her optimal, weil übersprungene X,Y,Z-Indexwerte keinen Speicherplatz verbrauchen und geht auch fix.

Das Ganze schön in eine Klasse gepackt und Zugriff per PropertyValue[x,y,z] und schon sieht es aus als wärs eine Array
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
445 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Mehrdimensionale Variable variabler Dimension

  Alt 11. Okt 2014, 13:00
Die Klasse sieht nun wie folgt aus:

Delphi-Quellcode:
TVariable<T> = Class
  private type
    PVariable = ^T;
  private
    fVarSize: Integer;
    fDimensions: TDimArray;
    fPData: PByte;
    fMemSize: Integer;
  public
    constructor Create(AName: AnsiString; const ADimensions: TDimArray); virtual;

    property Value_: T read GetValue write SetValue;
    property Value[x: Integer]: T read GetValue1D write SetValue1D; default;
    property Value[x,y: Integer]: T read GetValue2D write SetValue2D; default;
    property Value[x, y, z: Integer]: T read GetValue3D write SetValue3D; default;
  End;
Bis auf die Value_ property sieht das schon recht gut aus.

Zeitmessungen habe ich auch gemacht jeweils 800000 Zugriffe auf ein 10*3 Integer Array

Version mit Value[[x,y]] : ~2400ms
Version mit Value[x,y] : ~180ms

Zusätzlich habe ich auch das mit einem TDictionary ausprobiert:
Mit IntToStr(x)+'-'+IntToStr(y): ~9200ms
Mit (x Shl 16 + y) als Index: ~3400ms


Ein Problem bleibt noch mit der Unterscheidung zwischen:
Delphi-Quellcode:
Type
  TEnumEntry = AnsiString;
und "normalen" AnsiStrings. Beides soll als Array angelegt werden können, intern aber anders gehandhabt werden. AnsiStrings sind in Wirklichkeit Strings mit fixer Länge und können direkt abgelegt werden während TEnumEntry Strings mit varibler Länge sind und im Speicher einfach als Offsets auf ihre Position dahinter abgelegt werden sollen.

Leider ist aber TypeOf(T) = TypeOf(TEnumEntry) = TypeOf(AnsiString). Daher suche ich nun eine Möglichkeiten die beiden Varianten zu unterscheiden?
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Mehrdimensionale Variable variabler Dimension

  Alt 11. Okt 2014, 13:06
Ich finde diese Klasse einfach nur schrecklich (schon alleine wegen der Lesbarkeit der Quellcodes die die Klasse verwenden werden), aber wegen dem AnsiString, könnte man evtl. so machen?

TEnumEntry = type AnsiString;

Dann wären (für Delphi) TEnumEntry und AnsiString zwei unterschiedliche Typen.
  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
 
#6

AW: Mehrdimensionale Variable variabler Dimension

  Alt 11. Okt 2014, 14:50
Warum nicht so?
Delphi-Quellcode:
unit DimValue;

interface

uses
  System.Generics.Collections;

type
  IVariable<T> = interface
    function GetValue: T;
    procedure SetValue( const Value: T );
    property Value: T read GetValue write SetValue;
    function GetV( index: Integer ): IVariable<T>;
    procedure SetV( index: Integer; Value: IVariable<T> );
    property V[index: Integer]: IVariable<T> read GetV write SetV; default;
  end;

  TVariable<T> = class( TInterfacedObject, IVariable<T> )
  private
    FValue: T;
    FVarDict: TDictionary<Integer, IVariable<T>>;
  private
    function GetValue: T;
    procedure SetValue( const Value: T );
    function GetV( index: Integer ): IVariable<T>;
    procedure SetV( index: Integer; Value: IVariable<T> );
  private
    constructor Create;
    destructor Destroy; override;
  public
    class function Construct: IVariable<T>;
  end;

implementation

{ TVariable<T> }

class function TVariable<T>.Construct: IVariable<T>;
begin
  Result := TVariable<T>.Create;
end;

constructor TVariable<T>.Create;
begin
  inherited;
  FVarDict := TDictionary < Integer, IVariable < T >>.Create;
end;

destructor TVariable<T>.Destroy;
begin
  FVarDict.Free;
  inherited;
end;

function TVariable<T>.GetV( index: Integer ): IVariable<T>;
begin
  if not FVarDict.TryGetValue( index, Result )
  then
    begin
      Result := TVariable<T>.Construct;
      FVarDict.Add( index, Result );
    end;
end;

function TVariable<T>.GetValue: T;
begin
  Result := FValue;
end;

procedure TVariable<T>.SetV( index: Integer; Value: IVariable<T> );
begin
  FVarDict.AddOrSetValue( index, Value );
end;

procedure TVariable<T>.SetValue( const Value: T );
begin
  FValue := Value;
end;

end.
Jetzt hast du eine beliebige Dimensoinstiefe.
Delphi-Quellcode:
procedure foo;
var
  LVar : IVariable<string>;
begin
  LVar := TVariable<string>.Construct;
  LVar[0].Value := 'foo';
  LVar[0][0].Value := 'bar';
  LVar[0][0][0].Value := 'foobar';

  WriteLn( LVar[0].Value, ',', LVar[0][0].Value, ',', LVar[0][0][0].Value ); // => foo,bar,foobar
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
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
445 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Mehrdimensionale Variable variabler Dimension

  Alt 11. Okt 2014, 16:15
Warum nicht so?
...
Das siehst sehr elegant aus ! Vom zeitverhalten liege ich hier zwar bei ca 4000ms aber nach dem Ersetzen von TDictionary<> gegegen TArray<> bin ich auf 1800ms gekommen. Das ist zwar immer noch um den Faktor 10 langsamer würde aber die Sache mit den Strings elegant lösen.

Einziges Problem hier ist die Duplikation der Klasse. Ich hätte ein Liste mit vielen solcher Variablen (wird aus einem XML-File geladen/erstellt) und dann bei Bedarf an einen Thread übergeben. Dazu sollte die Liste bei der Übergabe geclont werden damit es zu keinen Seiteneffekten kommt.

Mit der ursprünglichen Variante wäre nur der Speicher (fPData^) zu kopieren gewesen wie das mit dieser Variante geht ist mir noch nicht ganz klar?
Whookie

Software isn't released ... it is allowed to escape!
  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
 
#8

AW: Mehrdimensionale Variable variabler Dimension

  Alt 11. Okt 2014, 17:01
Das mit dem Klonen geht auch ganz simpel, erstelle dir ein Clone Methode, die dann FValue kopiert und die Elemente aus dem (jetzt) Array (sind ja auch nur IVaraíable<T> wiederum clont.

Hier mal auf die Schnelle mit dem Dictionary:
Delphi-Quellcode:
function TVariable<T>.Clone : IVariable<T>;
begin
  Result := TVariable<T>.Construct;
  Result.Value := FValue;
  for LKey in FVarDict.Keys do
    Result[LKey] := FVarDict[LKey].Clone;
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
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
445 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Mehrdimensionale Variable variabler Dimension

  Alt 12. Okt 2014, 11:28
na klar , danke!
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
Antwort Antwort


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 10:24 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