|
|
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>
| |