Difference between revisions of "User:Nhollm"
(23 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | {{Warning|All of this is subject to change. Do '''NOT''' use it until its finished. | + | {{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'.}} |
− | ==Basic syntax== | + | Todo: |
+ | (TObjectDictionary)/ Classes as Values | ||
+ | |||
+ | ==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"> | <syntaxhighlight lang="pascal"> | ||
Line 11: | Line 20: | ||
type | type | ||
− | + | TStrStrDictionary = specialize TDictionary<string, string>; //specialize a new dictionary-object and set the desired data-type of key and value | |
var | var | ||
− | MyDictionary : | + | MyDictionary : TStrStrDictionary; |
begin | begin | ||
− | MyDictionary := | + | MyDictionary := TStrStrDictionary.Create; |
try | try | ||
//do stuff with your dictionary.. | //do stuff with your dictionary.. | ||
Line 26: | Line 35: | ||
</syntaxhighlight> | </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"> | <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 : TStrStrDictionary.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), true)); | ||
+ | </syntaxhighlight> | ||
− | + | ===ToArray=== | |
− | + | Returns an Array of type 'TDictionaryPair'.<br> | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | //var myArray : array of TStrStrDictionary.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 | |
− | + | 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(' | + | 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. | ||
+ | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | ==Exceptions== | ||
+ | To handle Exceptions, import the SysUtils Library. | ||
+ | <syntaxhighlight lang="pascal"> | ||
+ | {$mode objfpc} | ||
+ | program Example; | ||
+ | ... | ||
+ | uses | ||
+ | ... SysUtils; | ||
− | + | try | |
− | + | WriteLn(MyDictionary.Items['KeyXY']); // Accessing a non-existing key | |
− | + | except | |
− | |||
− | |||
− | |||
− | + | on E: Exception do begin | |
− | end | + | WriteLn('An exception was raised: ' + E.Message); |
+ | WriteLn(E.ClassName); | ||
+ | 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> | </syntaxhighlight> |
Latest revision as of 14:40, 2 September 2023
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: (TObjectDictionary)/ Classes as Values
TDictionary
TDictionary is a generic Data-Container for Key-value pairs (associative array).
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.
Basic syntax (FPC)
{$mode objfpc}
program Example;
uses
Generics.Collections; //import the generics-library of the RTL
type
TStrStrDictionary = specialize TDictionary<string, string>; //specialize a new dictionary-object and set the desired data-type of key and value
var
MyDictionary : TStrStrDictionary;
begin
MyDictionary := TStrStrDictionary.Create;
try
//do stuff with your dictionary..
finally
MyDictionary.Free;
end;
end.
Usage:
Add
Add Entry or update its current value (key, value)
MyDictionary.AddOrSetValue('Key1', 'Value1');
The function AddOrSetValue is recommended.
Alternatively there is the Function Add().
Add() will throw an error if the Key already exists: 'Dublicate Not Allowed in Dictionary'.
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
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
If you want to get a feedback, use these functions. They 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.