Wie festes Dictionary vordefinieren?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie festes Dictionary vordefinieren?

Beitrag von af0815 »

Erinnert mich irgendwie an das Zahlenraten auf einen TI-58 bzw. SR 56.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: Wie festes Dictionary vordefinieren?

Beitrag von photor »

sstvmaster hat geschrieben:Oder vieleicht auch das:

Code: Alles auswählen

 
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
 
  public
 
  end;
 
var
  Form1: TForm1;
 
implementation
 
uses
  contnrs;
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
var
  Dictionary : TFPStringHashTable;
begin
  Dictionary := TFPStringHashTable.Create;
  try
    Dictionary.Add('key1', 'Wort1');
    Dictionary.Add('key2', 'Wort2');
    Dictionary.Add('key3', 'Wort3');
    Dictionary.Add('key4', 'Wort4');
 
    // Key based access to the strings in the hash table
    ShowMessage(Dictionary.Items['key1']);
 
  finally
    Dictionary.Free;
  end;
 
end;
 
end
 


Bei so einer Lösung war auch schon angekommen. Muss halt einmal am Anfang alle Werte einzeln in's TDictionary packen. Geht bestimmt, ist aber nicht soo elegant. Aber ja, geht.

Ciao,
Photor

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: Wie festes Dictionary vordefinieren?

Beitrag von photor »

Warf hat geschrieben:TFPGMap<Integer, String> mit sorted auf true gesetzt hat eine lookup Laufzeit von log(n) und einen speicherverbrauch von n

Alternativ TMap aus der gmap unit implementiert das ganze soweot ich weiss über einen rbt, was etwas performanter sein kann.


Ah, TMap bzw. TFPGMap kannte ich noch nicht. Das schau ich mir mal an.

Danke,
Photor

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Wie festes Dictionary vordefinieren?

Beitrag von sstvmaster »

geht auch so:

Code: Alles auswählen

 
...
type
  TDictArray = array[0..3, 0..1] of string;
 
const
  DictArray: TDictArray = (
    ('key1','Wort1'),
    ('key2','Wort2'),
    ('key3','Wort3'),
    ('key4','Wort4')
  );
 
var
  Dictionary : TFPStringHashTable;
  i: Integer;
begin
  Dictionary := TFPStringHashTable.Create;
  try
    for i := 0 to High(DictArray) do begin
      Dictionary.Add(DictArray[i][0], DictArray[i][1]);
    end;
    // Key based access to the strings in the hash table
    ShowMessage(Dictionary.Items['key1']);
  finally
    Dictionary.Free;
  end;
end;
 
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Wie festes Dictionary vordefinieren?

Beitrag von Warf »

photor hat geschrieben:Ah, TMap bzw. TFPGMap kannte ich noch nicht. Das schau ich mir mal an.

Danke,
Photor

Ist ziemlich straight forward, hier mal ein beispiel:

Code: Alles auswählen

program Project1;
 
{$mode objfpc}{$H+}
 
uses
  classes, sysutils, fgl;
 
type
 
  { TIntStringMap }
 
  TIntStringMap = class(specialize TFPGMap<Integer, String>)
  public
    constructor Create;
  end;
 
{ TIntStringMap }
 
constructor TIntStringMap.Create;
begin
  inherited Create;
  Sorted:=True;
  Duplicates:=dupError;
end;
 
var map: TIntStringMap;
  inp: String;
  sel, i: Integer;
begin
  map := TIntStringMap.Create;
  try
    repeat
      WriteLn('(1) Add entry');
      WriteLn('(2) Show entry');
      WriteLn('(3) All Entries');
      WriteLn('(4) Delete Entry');
      ReadLn(sel);
      case sel of
      1: begin
        Write('Number: ');
        Readln(sel);
        Write('Text: ');
        Readln(inp);
        map[sel] := inp;
      end;
      2: begin 
        Write('Number: ');
        Readln(sel);
        WriteLn(map[sel]);
      end;
      3: begin
        for i:=0 to map.Count-1 do
          WriteLn(map.Keys[i], ': ', map.Data[i]);
      end;
      4: begin
        Write('Number: ');
        Readln(sel);
        map.Remove(sel);
      end;
      else break;
      end;
    until False;
  finally
    map.Free;
  end;
end.
 


Ich leite immer ne eigene klasse ab bei der ich Create überschreibe, damit ich nicht jedes mal sorted auf true setzen muss (wenn ich ne map habe will ich das eh, kommt ganz selten vor das die reihenfolge der einträge relevant ist)

Benutzeravatar
Swirl
Beiträge: 93
Registriert: Fr 7. Aug 2015, 14:05
OS, Lazarus, FPC: Win 10/11/ Mint 21.3 / Lazarus 30 / FPC 3.2.2
CPU-Target: x86_64, ARM Cort.-A7
Wohnort: Schwerte NRW

Re: Wie festes Dictionary vordefinieren?

Beitrag von Swirl »

Muss sich das alles im Speicher abspielen? Bzw. wäre es mit Kanonen auf Spatzen geschossen, das mit einer SQLite-Tabelle zu erschlagen?
Zumindest wäre die binäre Suche bei der entsprechenden Indizierung Sache des DBS.
=> Mint 21.3 “Virginia” - Win 10/11 - Lazarus 3.0 - FPC 3.2.2

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie festes Dictionary vordefinieren?

Beitrag von af0815 »

Swirl hat geschrieben:Muss sich das alles im Speicher abspielen? Bzw. wäre es mit Kanonen auf Spatzen geschossen, das mit einer SQLite-Tabelle zu erschlagen?
Zumindest wäre die binäre Suche bei der entsprechenden Indizierung Sache des DBS.

Eher umgekehrt, wegen der paar Daten eine komplette DB zu nehmen ist mit Kanonen auf Spatzen zu schiessen. Vor allen wenn man bedenkt, das das DBMS noch dazu extra in den Speicher geladen werden muss und das seinerseits natürlich die Tabellen und Indizies im Speicher vorhält. Und auch die DB muss ja die Indizies irgendwie erstellen und hält das als Hashtable oder ähnlich im Speicher. Dazu jedesmal über das Interface gehen oder es halten die DB-Komponenten wieder lokal alles im Speicher.

Nein, man muß irgendwo schon sagen, das die Kirche im Dorf bleiben soll. Vor allen, wenn das so einfach abzuwickeln ist.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Swirl
Beiträge: 93
Registriert: Fr 7. Aug 2015, 14:05
OS, Lazarus, FPC: Win 10/11/ Mint 21.3 / Lazarus 30 / FPC 3.2.2
CPU-Target: x86_64, ARM Cort.-A7
Wohnort: Schwerte NRW

Re: Wie festes Dictionary vordefinieren?

Beitrag von Swirl »

Hallo af0815

Da hast du wohl etwas fix gelesen...
Eher umgekehrt, wegen der paar Daten eine komplette DB zu nehmen ist mit Kanonen auf Spatzen zu schiessen


Ich hatte ja gerade gefragt, ob es nicht ein Kanonen auf Spatzen Schießen sei, SQLite zu benutzen.
Und außerdem finde ich den Begriff Datenbank etwas übertrieben; ich fände da den Begriff Tabelle angemessener. Und das DBMS lässt sich letzten Endes auf sqlite3.dll bzw sqlite3xxx.so reduzieren.

Schönes WE
Michael
=> Mint 21.3 “Virginia” - Win 10/11 - Lazarus 3.0 - FPC 3.2.2

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie festes Dictionary vordefinieren?

Beitrag von af0815 »

Swirl hat geschrieben:Hallo af0815

Da hast du wohl etwas fix gelesen...
Eher umgekehrt, wegen der paar Daten eine komplette DB zu nehmen ist mit Kanonen auf Spatzen zu schiessen


Nicht nicht richtig lesen ist nicht umständlich :-) Sorry.
Swirl hat geschrieben:Und außerdem finde ich den Begriff Datenbank etwas übertrieben; ich fände da den Begriff Tabelle angemessener. Und das DBMS lässt sich letzten Endes auf sqlite3.dll bzw sqlite3xxx.so reduzieren.

Es lässt sich nicht reduzieren, die Library ist genaugenommen das DBMS, zusätzlich musst du immer den Overhead der Komponenten in Lazarus/FPC einbeziehen. Die ja letztlich wieder die Libraries laden. Dazu der ganze interen Aufwand.

Ich arbeite mein halbes Leben mit Datenbanken und auch meinen Unterhalt (wenn nicht gerade Corona-Shutdown ist). Trotzdem verwende ich die verschiedenen Listen und auch Collection gerne, sind sinnvoll und sehr gut in der Performance.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Wie festes Dictionary vordefinieren?

Beitrag von BeniBela »

Ich habe hier einen Benchmark von den ganzen Klassen

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie festes Dictionary vordefinieren?

Beitrag von af0815 »

BeniBela hat geschrieben:Ich habe hier einen Benchmark von den ganzen Klassen


Kommt nach ein paar Sekunden:
Fehlercode: RESULT_CODE_INVALID_CMDLINE_URL

auf Debian Buster
Chrome Version 81.0.4044.113 (Offizieller Build) (64-Bit)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Wie festes Dictionary vordefinieren?

Beitrag von BeniBela »

af0815 hat geschrieben:
BeniBela hat geschrieben:Ich habe hier einen Benchmark von den ganzen Klassen


Kommt nach ein paar Sekunden:
Fehlercode: RESULT_CODE_INVALID_CMDLINE_URL

auf Debian Buster
Chrome Version 81.0.4044.113 (Offizieller Build) (64-Bit)


Was macht Chrome denn da? Unter Firefox gibt es keine Probleme.

edit: habe eine neue Version hochgeladen. Mit neuer Chart.js. 12 neuen Klassen und fpc 3.3.1 statt 3.1.1

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie festes Dictionary vordefinieren?

Beitrag von af0815 »

Danke gute Übersicht. Wusste gar nicht wieviele Möglichkeiten und die VT/NT
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Wie festes Dictionary vordefinieren?

Beitrag von Warf »

BeniBela hat geschrieben:Ich habe hier einen Benchmark von den ganzen Klassen

Cooler Benchmark, aber man muss natürlich auch beachten das TFPDataHashTable und TFPHashList nur pointer als value erlauben. Klar kann man unter x86_64 CPUs auch integer rein schieben, ist aber nicht portable, wirft ne warning und ist, wenn ich das mal so sagen darf, kein sauberer Stil. Um also was anderes als TObjects reinzuschieben, muss man indirection verwenden, was bei TFPGMap oder gHashMap.THashMap nicht der Fall ist. Das kann die benchmarks natürlich beinflussen.
Das nächste ist das keys natürlich mehr als strings sein können. Einen nicht string erst mal zu string serialisieren um dann den lookup zu machen beeinflusst natürlich auch die Zugriffszeit, besonders bei komplexeren datentypen wie records.
Und natürlich ist es auch eine frage was man damit macht. Z.b. wäre es auch interessant wie hoch die geschwindigkeit beim löschen von elementen und drüber iterieren ist. Ich würde vermuten das das drüber iterieren bei TFPGMap deutlich schneller sein sollte als bei den HashMap counterparts.

Das gesagt ist so eine übersicht natürlich schon cool. Vor allem weil du auch nicht standard bibliotheken drin hast. Denn TFPDataHashTable und TFPHashList wegen der "string-pointer" zuweisung m.M.n. keine wirkliche alternative darstellt (allein die tatsache das man das Memory-Management für die daten übernhemen muss), sehen die alternativen in den Standardbibliotheken eher mau aus. TFPGMap, gmap.TMap und ghashmap.THashMap sind so wie ich das sehe da die einzigen Optionen die standardmäßig verfügbar sind.

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: Wie festes Dictionary vordefinieren?

Beitrag von photor »

sstvmaster hat geschrieben:geht auch so:

Code: Alles auswählen

 
...
type
  TDictArray = array[0..3, 0..1] of string;
 
const
  DictArray: TDictArray = (
    ('key1','Wort1'),
    ('key2','Wort2'),
    ('key3','Wort3'),
    ('key4','Wort4')
  );
 
var
  Dictionary : TFPStringHashTable;
  i: Integer;
 

Sowas in der Art hatte ich auch schon probiert - gab aber Fehlermeldungen. Die hab ich leider nicht aufgeschrieben und kann nicht mehr sagen, warum das nicht tat. Ich probiere es einfach nochmal. Danke,

Photor

Antworten