Difference between revisions of "User:Nhollm"

From Free Pascal wiki
Jump to navigationJump to search
(Blanked the page)
Tag: Blanking
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'.}}
 
  
Todo:
 
Exceptions
 
Dictionarys with Classes (TObjectDictionary)
 
 
==TDictionary==
 
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>
 
 
 
==Basic syntax (FPC)==
 
 
<syntaxhighlight lang="pascal">
 
{$mode objfpc}
 
program Example;
 
 
uses
 
Generics.Collections;  //import the generics-library of the RTL
 
 
type
 
TStringStringDictionary =  specialize TDictionary<string, string>; //specialize a new dictionary-object and set the desired data-type of key and value
 
 
var
 
  MyDictionary : TStringStringDictionary;
 
begin
 
  MyDictionary := TStringStringDictionary.Create;
 
  try
 
    //do stuff with your dictionary..
 
  finally
 
    MyDictionary.Free;
 
  end;
 
end.
 
 
</syntaxhighlight>
 
 
==Usage:==
 
 
<syntaxhighlight lang="pascal">
 
</syntaxhighlight>
 
 
===Add===
 
Add Entry or update its current value (key, value)
 
<syntaxhighlight lang="pascal">
 
MyDictionary.AddOrSetValue('Key1', 'Value1');
 
</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===
 
<syntaxhighlight lang="pascal">
 
MyDictionary.Remove('Key2');
 
</syntaxhighlight>
 
If the Key does not exist, no Error is thrown.
 
 
===Clear===
 
<syntaxhighlight lang="pascal">
 
MyDictionary.Clear;
 
</syntaxhighlight>
 
 
===Get Value===
 
<syntaxhighlight lang="pascal">
 
WriteLn(MyDictionary.Items['Key1']);
 
</syntaxhighlight>
 
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)
 
<syntaxhighlight lang="pascal">
 
WriteLn('Items in Dictionary: ' + IntToStr(MyDictionary.Count));
 
</syntaxhighlight>
 
 
===Loops===
 
<syntaxhighlight lang="pascal">
 
//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 : TStringStringDictionary.TDictionaryPair;
 
for KeyValuePair in MyDictionary do
 
  WriteLn('Found a Pair: Key:' + KeyValuePair.Key + ' Value:' + KeyValuePair.Value);
 
</syntaxhighlight>
 
 
===Check If Key/Value Exists===
 
 
<syntaxhighlight lang="pascal">
 
//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');
 
</syntaxhighlight>
 
 
===Trying===
 
If you want to get a feedback, use these functions. They return a boolean.<br>
 
True if sucessfull, False if not. No Error is thrown, so they are a good alternative to GetValue or Add.
 
 
====TryAdd====
 
<syntaxhighlight lang="pascal">
 
if MyDictionary.TryAdd('Key','TestValue') then
 
  writeln('added successfully')
 
else
 
  writeln('not sucessfull');
 
</syntaxhighlight>
 
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.<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.
 
 
<syntaxhighlight lang="pascal">
 
 
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)));
 
</syntaxhighlight>
 
 
===ToArray===
 
Returns an Array of type 'TDictionaryPair'.<br>
 
<syntaxhighlight lang="pascal">
 
//var myArray :  array of TStringStringDictionary.TDictionaryPair;
 
myArray := MyDictionary.ToArray()
 
//WriteLn(length(myArray));
 
//WriteLn(myArray[0].Key)
 
//WriteLn(myArray[0].Value)
 
</syntaxhighlight>
 
 
==Event Notifications==
 
You can set up custom Functions/Procedures which are triggered if an Key or Value got added/removed.<br>
 
To do this, we add 2 procedures to the class we specialize from TDictionary.<br>
 
The TDictionary class provides the in-build functions 'OnKeyNotify' and 'OnValueNotify'. Now we assign them to our procedures.<br>
 
(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
 
 
<syntaxhighlight lang="pascal" highlight="10,11,41,42">
 
{$mode objfpc}
 
program Example;
 
 
uses
 
Generics.Collections;
 
 
type
 
TStringStringDictionary = 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 TStringStringDictionary.DoKeyNotify(ASender: TObject;constref AItem: ShortString; AAction: TCollectionNotification);
 
  begin
 
        //WriteLn(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 TStringStringDictionary.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 : TStringStringDictionary;
 
  TestArr : array of TStringStringDictionary.TDictionaryPair;
 
begin
 
  MyDictionary := TStringStringDictionary.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.
 
</syntaxhighlight>
 
 
 
==Exceptions==
 
To handle Exceptions, import the SysUtils Library.
 
<syntaxhighlight lang="pascal">
 
{$mode objfpc}
 
program Example;
 
 
uses
 
Generics.Collections,SysUtils;
 
 
type
 
TStringStringDictionary =  specialize TDictionary<string, string>;
 
 
var
 
  MyDictionary : TStringStringDictionary;
 
begin
 
  MyDictionary := TStringStringDictionary.Create;
 
  try
 
 
      try         
 
          WriteLn(MyDictionary.Items['KeyXY']); // Accessing a non exiting key
 
        except
 
 
            on E: Exception do begin
 
              WriteLn('An exception was raised: ' + E.Message);
 
              WriteLn(E.ClassName);
 
 
            end;
 
 
        end;
 
        ReadLn();
 
  finally
 
    MyDictionary.Free;
 
  end;
 
end.
 
 
//Output: An exception was raised: Dictionary key does not exist
 
//EListError
 
</syntaxhighlight>
 
 
 
 
==Delphi==
 
<syntaxhighlight lang="pascal">
 
{$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.
 
</syntaxhighlight>
 

Revision as of 01:08, 15 May 2023