Difference between revisions of "User:Nhollm"
(→TryAdd) |
(→TDictionary: removed wrong statement) |
||
Line 5: | Line 5: | ||
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> | ||
− | A TDictionary is unordered | + | A TDictionary is unordered<br> |
more technical details here <br><br> | more technical details here <br><br> |
Revision as of 09:16, 11 May 2024
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
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 fail, if the key already exists
'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');
Limitation: 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.