Difference between revisions of "User:Nhollm"

From Lazarus wiki
Jump to navigationJump to search
m (Minor restructure and spelling)
Line 1: Line 1:
{{Warning|All of this is subject to change. Do '''NOT''' use it until its finished. For any Questions or Input write me an E-Mail ich@nhollm.de or write me at the forums 'nhollm'.}}
+
{{Warning|All of this is subject to change. Do '''NOT''' use it until its finished. For any Questions or Input write me an E-Mail nhollm@gmx.de or write me at the forums 'nhollm'.}}
  
Todo:
 
(TObjectDictionary)/ Classes as Values
 
  
 
==TDictionary==
 
==TDictionary==
TDictionary is a generic Data-Container for Key-value pairs (associative array). <br>
+
TDictionary is a generic data-container for key-value pairs (associative array). <br>
  
It was introduced with Generics.Collections in FPC 3.2.0 (June 2020). It's part of the FPC Runtime Library and fully Delphi compatible.<br>
+
A TDictionary is unordered, this means you cannot refer its items by index. <br>
  
 +
more technical details here <br><br>
 +
 +
It was introduced with Generics.Collections in FPC 3.2.0 (June 2020)????. It's part of the FPC Runtime Library and fully Delphi compatible.<br>
 +
 +
credit to author?<br>
  
 
==Basic syntax (FPC)==
 
==Basic syntax (FPC)==
Line 17: Line 20:
  
 
uses
 
uses
Generics.Collections; //import the generics-library of the RTL
+
Generics.Collections;
  
 
type
 
type
TStrStrDictionary =  specialize TDictionary<string, string>; //specialize a new dictionary-object and set the desired data-type of key and value
+
TStrStrDictionary =  specialize TDictionary<string, string>;
  
 
var
 
var
Line 41: Line 44:
  
 
===Add===
 
===Add===
Add Entry or update its current value (key, value)
+
'''AddOrSetValue()''' is recommended, because '''Add()''' will not overwrite existing keys<br>
 +
Instead it will throw an error: 'Dublicate not allowed in Dictionary'.<br>
 +
 
 +
====Add====
 +
<syntaxhighlight lang="pascal">
 +
MyDictionary.Add('Key1', 'Value1');
 +
</syntaxhighlight>
 +
 
 +
====AddOrSetValue====
 +
recommended
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
MyDictionary.AddOrSetValue('Key1', 'Value1');
 
MyDictionary.AddOrSetValue('Key1', 'Value1');
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The function AddOrSetValue is recommended.<br>
 
Alternatively there is the Function '''Add()'''.<br>
 
'''Add()''' will throw an error if the Key already exists: 'Dublicate Not Allowed in Dictionary'.<br>
 
If you only want to add new Items and not overwrite them in the case they exist, take a look at TryAdd() below. It provides a feedback too.
 
  
 
===Remove===
 
===Remove===
Line 71: Line 79:
 
Total number of Items in dictionary (count)
 
Total number of Items in dictionary (count)
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
WriteLn('Items in Dictionary: ' + IntToStr(MyDictionary.Count));
+
WriteLn('Items in Dictionary: ', IntToStr(MyDictionary.Count));
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
===Loops===
 
===Loops===
 +
 +
====Loop Keys====
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
//Loop Keys
 
 
for KeyStr in MyDictionary.Keys do
 
for KeyStr in MyDictionary.Keys do
   WriteLn('Found key:' + KeyStr);
+
   WriteLn('Found key:', KeyStr);
 +
</syntaxhighlight>
  
 
+
====Loop Values====
//Loop Values
+
<syntaxhighlight lang="pascal">
 
for ValueStr in MyDictionary.Values do
 
for ValueStr in MyDictionary.Values do
   WriteLn('Found Value: ' + ValueStr);
+
   WriteLn('Found Value: ', ValueStr);
 +
</syntaxhighlight>
  
 
+
====Loop Key-Value-Pairs====
//Loop Key-Value-Pairs
+
<syntaxhighlight lang="pascal">
 
//var KeyValuePair : TStrStrDictionary.TDictionaryPair;
 
//var KeyValuePair : TStrStrDictionary.TDictionaryPair;
 
for KeyValuePair in MyDictionary do
 
for KeyValuePair in MyDictionary do
   WriteLn('Found a Pair: Key:' + KeyValuePair.Key + ' Value:' + KeyValuePair.Value);
+
   WriteLn('Found a Pair: Key:' , KeyValuePair.Key , ' Value:' , KeyValuePair.Value);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 110: Line 121:
  
 
===Trying===
 
===Trying===
If you want to get a feedback, use these functions. They return a boolean.<br>
+
These functions return a boolean.<br>
True if sucessfull, False if not. No Error is thrown, so they are a good alternative to GetValue or Add.
+
True if sucessfull, False if not. No error is thrown, so they are a good alternative to GetValue() or Add().
  
 
====TryAdd====
 
====TryAdd====
Line 124: Line 135:
 
TryGetValue takes two Arguments ->(key, value) and returns a boolean.<br>
 
TryGetValue takes two Arguments ->(key, value) and returns a boolean.<br>
 
If found, it returns '''True''' and the provided 'value' variable becomes the value.<br>
 
If found, it returns '''True''' and the provided 'value' variable becomes the value.<br>
If not found, the function returns '''False''' and the provided 'value'-variable is nil.
+
If not found, the function returns '''False''' and the provided 'value'-variable is '''nil'''.
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 198: Line 209:
  
 
   try
 
   try
     MyDictionary.AddOrSetValue('Key1', 'Value1');//triggers Add Event
+
     MyDictionary.AddOrSetValue('Key1', 'Value1');//triggers 'Add' Event
     MyDictionary.AddOrSetValue('Key1', 'New Value');//triggers Add and Remove Event
+
     MyDictionary.AddOrSetValue('Key1', 'New Value');//triggers 'Add' and 'Remove' Event
     MyDictionary.Remove('Key1');//triggers Remove Event
+
     MyDictionary.Remove('Key1');//triggers 'Remove' Event
 
     readln();
 
     readln();
 
   finally
 
   finally
Line 223: Line 234:
  
 
   on E: Exception do begin
 
   on E: Exception do begin
       WriteLn('An exception was raised: ' + E.Message);
+
       WriteLn('An exception was raised: ', E.Message);
 
       WriteLn(E.ClassName);
 
       WriteLn(E.ClassName);
 
   end;
 
   end;

Revision as of 09:08, 11 May 2024

Warning-icon.png

Warning: All of this is subject to change. Do NOT use it until its finished. For any Questions or Input write me an E-Mail nhollm@gmx.de or write me at the forums 'nhollm'.


TDictionary

TDictionary is a generic data-container for key-value pairs (associative array).

A TDictionary is unordered, this means you cannot refer its items by index.

more technical details here

It was introduced with Generics.Collections in FPC 3.2.0 (June 2020)????. It's part of the FPC Runtime Library and fully Delphi compatible.

credit to author?

Basic syntax (FPC)

{$mode objfpc}
program Example;

uses
Generics.Collections;

type
TStrStrDictionary =  specialize TDictionary<string, string>;

var
  MyDictionary : TStrStrDictionary;
begin
  MyDictionary := TStrStrDictionary.Create;
  try
    //do stuff with your dictionary..
  finally
    MyDictionary.Free;
  end;
end.

Usage:

Add

AddOrSetValue() is recommended, because Add() will not overwrite existing keys
Instead it will throw an error: 'Dublicate not allowed in Dictionary'.

Add

MyDictionary.Add('Key1', 'Value1');

AddOrSetValue

recommended

MyDictionary.AddOrSetValue('Key1', 'Value1');


Remove

MyDictionary.Remove('Key2');

If the Key does not exist, no Error is thrown.

Clear

MyDictionary.Clear;

Get Value

WriteLn(MyDictionary.Items['Key1']);

If the provided key does not exist, this will throw an Error: 'Dictionary Key does not Exist'. You can use 'TryGetValue' instead.

Item Count

Total number of Items in dictionary (count)

WriteLn('Items in Dictionary: ', IntToStr(MyDictionary.Count));

Loops

Loop Keys

for KeyStr in MyDictionary.Keys do
  WriteLn('Found key:', KeyStr);

Loop Values

for ValueStr in MyDictionary.Values do
  WriteLn('Found Value: ', ValueStr);

Loop Key-Value-Pairs

//var KeyValuePair : TStrStrDictionary.TDictionaryPair;
for KeyValuePair in MyDictionary do
  WriteLn('Found a Pair: Key:' , KeyValuePair.Key , ' Value:' , KeyValuePair.Value);

Check If Key/Value Exists

//Check if Key exists
if MyDictionary.ContainsKey('Key1') then
  WriteLn('key exists')
else
  WriteLn('key not found');


//Check if Value exists
if MyDictionary.ContainsValue('Searched value') then
  writeln('value exists')
else
  writeln('value not found');

Trying

These functions return a boolean.
True if sucessfull, False if not. No error is thrown, so they are a good alternative to GetValue() or Add().

TryAdd

if MyDictionary.TryAdd('Key','TestValue') then
  writeln('added successfully')
else
  writeln('not sucessfull');

TryAdd does not update an existing keys value. Use AddOrSetValue instead. (Even tho there is no feedback provided)

TryGetValue

TryGetValue takes two Arguments ->(key, value) and returns a boolean.
If found, it returns True and the provided 'value' variable becomes the value.
If not found, the function returns False and the provided 'value'-variable is nil.

if MyDictionary.TryGetValue('Key', SearchedValue) then
  WriteLn('Key found. Its value is: ' + SearchedValue)
else
  WriteLn('Could not get value');

//writeln(BoolToStr(MyDictionary.TryGetValue('Key', SearchedValue), true));

ToArray

Returns an Array of type 'TDictionaryPair'.

//var myArray :  array of TStrStrDictionary.TDictionaryPair;
myArray := MyDictionary.ToArray()
//WriteLn(length(myArray));
//WriteLn(myArray[0].Key)
//WriteLn(myArray[0].Value)

Event Notifications

You can set up custom Functions/Procedures which are triggered if an Key or Value got added/removed.
To do this, we add 2 procedures to the class we specialize from TDictionary.
The TDictionary class provides the in-build functions 'OnKeyNotify' and 'OnValueNotify'. Now we assign them to our procedures.
(Hint: If you update a existing value, there is no "updated"Event. Instead "removed" followed by "added" is triggered.) TODO: get the Key Name inside the ValueNotify-Event kontext

{$mode objfpc}
program Example;

uses
Generics.Collections;

type
TStrStrDictionary = Class(Specialize TDictionary<String,String>)
  private
    procedure DoKeyNotify(ASender: TObject;constref AItem: ShortString; AAction: TCollectionNotification);
    procedure DoValueNotify(ASender: TObject;constref AItem: ShortString; AAction: TCollectionNotification);
  end;

procedure TStrStrDictionary.DoKeyNotify(ASender: TObject;constref AItem: ShortString; AAction: TCollectionNotification);
   begin
        //WriteLn(AAction);//AAction can be 'cnRemoved' or 'cnAdded'
        if AAction = cnAdded then
           writeln('A Key got added, the Key is:', AItem)
        else if AAction = cnRemoved then
            writeln('A Key got removed, the Key was:', AItem)
   end;

procedure TStrStrDictionary.DoValueNotify(ASender: TObject;constref AItem: ShortString; AAction: TCollectionNotification);
   begin
        Writeln(AAction);//can be cnRemoved or cnAdded
        if AAction = cnAdded then
          writeln('A Value got added, the value is:', AItem)
        else if AAction = cnRemoved then
          writeln('A Value got removed, the value was:', AItem)
   end;



var
  MyDictionary : TStrStrDictionary;
  TestArr : array of TStrStrDictionary.TDictionaryPair;
begin
  MyDictionary := TStrStrDictionary.Create;

  //Event notifications:
  MyDictionary.OnKeyNotify:=@MyDictionary.DoKeyNotify;
  MyDictionary.OnValueNotify:=@MyDictionary.DoValueNotify;

  try
    MyDictionary.AddOrSetValue('Key1', 'Value1');//triggers 'Add' Event
    MyDictionary.AddOrSetValue('Key1', 'New Value');//triggers 'Add' and 'Remove' Event
    MyDictionary.Remove('Key1');//triggers 'Remove' Event
    readln();
  finally
    MyDictionary.Free;
  end;
end.


Exceptions

To handle Exceptions, import the SysUtils Library.

{$mode objfpc}
program Example;
...
uses
... SysUtils;

try          
   WriteLn(MyDictionary.Items['KeyXY']); // Accessing a non-existing key 
except

   on E: Exception do begin
      WriteLn('An exception was raised: ', E.Message);
      WriteLn(E.ClassName);
   end;

end;

//Output:
// An exception was raised: Dictionary key does not exist
//EListError

Delphi

{$mode delphi}
uses generics.collections;
 
type  TStrIntDict = TDictionary<string,integer>;
 
    var
      MyDict : TStrIntDict;
    begin
      MyDict:=TStrIntDict.create;
      MyDict.AddorSetValue('foo',42);
      if MyDict.ContainsKey('foo') then
        WriteLn(MyDict['foo']);
    end.