sharing the code on this question as reference: Delphi TPair Exception
How can I retrieve the key and value from a TObjectDictionary concrete entry without using TPair and without extracting/remove/delete the pair from the list ?
{$APPTYPE CONSOLE}
uses
SysUtils,
Generics.Defaults,
Generics.Collections;
type
TProduct = class
private
FName: string;
procedure SetName(const Value: string);
published
public
property Name: string read FName write SetName;
end;
type
TListOfProducts = TObjectDictionary<TProduct, Integer>;
{ TProduct }
procedure TProduct.SetName(const Value: string);
begin
FName := Value;
end;
var
MyDict: TListOfProducts;
MyProduct1: TProduct;
MyProduct2: TProduct;
MyProduct3: TProduct;
APair: TPair<TProduct, Integer>;
aKey: string;
begin
try
MyDict := TListOfProducts.Create([doOwnsKeys]);
MyProduct1 := TProduct.Create;
MyProduct1.Name := 'P1';
MyProduct2 := TProduct.Create;
MyProduct2.Name := 'P2';
MyProduct3 := TProduct.Create;
MyProduct3.Name := 'P3';
MyDict.Add(MyProduct1, 1);
MyDict.Add(MyProduct2, 2);
MyDict.Add(MyProduct3, 3);
//the code to look for a **concrete product** (ie: MyProduct1) goes here..
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Thanks.
=========================
{$APPTYPE CONSOLE}
uses
SysUtils,
Generics.Defaults,
Generics.Collections;
type
TProduct = class
private
FName: string;
procedure SetName(const Value: string);
published
public
property Name: string read FName write SetName;
end;
type
TListOfProducts = TObjectDictionary<TProduct, Integer>;
{ TProduct }
procedure TProduct.SetName(const Value: string);
begin
FName := Value;
end;
var
MyDict: TListOfProducts;
MyProduct1: TProduct;
MyProduct2: TProduct;
MyProduct3: TProduct;
MySearchedProduct: TProduct; // From Answer.
APair: TPair<TProduct, Integer>;
aProductName: string;
begin
try
MyDict := TListOfProducts.Create([doOwnsKeys]);
MyProduct1 := TProduct.Create;
MyProduct1.Name := 'P1';
MyProduct2 := TProduct.Create;
MyProduct2.Name := 'P2';
MyProduct3 := TProduct.Create;
MyProduct3.Name := 'P3';
MyDict.Add(MyProduct1, 1);
MyDict.Add(MyProduct2, 2);
MyDict.Add(MyProduct3, 3);
Writeln('Enter the Product Name to search: ');
//the code to look for a **concrete product** goes here..
Readln(aProductName);
for MySearchedProduct in Mydict.Keys do
if (MySearchedProduct.Name = aProductName) then
break;
if MySearchedProduct.Name = aProductName then
WriteLn('I have found the product: ' + MySearchedProduct.Name)
else
WriteLn('I have not found a product with that name.');
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
You can use The Keys
and Values
properties of MyDict.
In a loop like this:
var
MyProduct: TProduct;
Value: Integer;
begin
for Value in MyDict.Values do
writeln(Value);
for MyProduct in MyDict.Keys do
writeln(MyProduct.Name);
Or by index using ToArray
:
writeln(MyDict.Keys.ToArray[1].Name);
writeln(MyDict.Values.ToArray[1]);
The Key
and Value
are saved in the dictionary as a TPair<TKey,TValue>
. If you need to work with both key and value, the logical thing to do is use a TPair
;
Looks like this:
for APair in MyDict do
begin
// Your stuff goes here.
end;
If for some reason you don't want to use TPair to extract the pairs you may use something like this, but this is absolutely not a good idea - you're doing lots of dictionary queries for no good reason:
for AKey in MyDict.Keys do
begin
AValue := MyDict[AKey];
// Do something with both AKey and AValue
end;
Looping through the keys could be extrimely slow if your dictionary contains lots of members. I suggest keeping the key in the Pair along with the real value. Considering the example provided it might look like this:
type
TListOfProducts = TObjectDictionary<TProduct, TPair<TProduct,Integer>>;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With