我希望有一个返回默认值的字典,在搜索键未找到时能够使用。根据文档所述:
Generics.Collections.Tdictionary […] 此类提供映射 […] 和初始内容。
1 - 如何实现?是否可以像 Python 一样:{1: ‘one’, 2:’two’}?
Generics.Collections.TDictionary.TryGetValue [...] 如果给定键在字典中,则TryGetValue 返回 true,并在 Value 中提供其值。否则,它返回 false 并将 Value 设置为 Tvalue 的默认值类型。
2 - 我该如何设定此默认值?我无法找到构造函数 (也许我只是在错误的地方搜索。我期望会有像 “constructor Create(DefaultValue: TValue);” 这样的函数)
因此我尝试自己实现(也许不必要。见上):
以下是代码 (欢迎评论和建议!):
Generics.Collections.Tdictionary […] 此类提供映射 […] 和初始内容。
1 - 如何实现?是否可以像 Python 一样:{1: ‘one’, 2:’two’}?
Generics.Collections.TDictionary.TryGetValue [...] 如果给定键在字典中,则TryGetValue 返回 true,并在 Value 中提供其值。否则,它返回 false 并将 Value 设置为 Tvalue 的默认值类型。
2 - 我该如何设定此默认值?我无法找到构造函数 (也许我只是在错误的地方搜索。我期望会有像 “constructor Create(DefaultValue: TValue);” 这样的函数)
因此我尝试自己实现(也许不必要。见上):
以下是代码 (欢迎评论和建议!):
unit Util;
interface
uses
Generics.collections;
type
//
// Dictionary with default response
//
TDefaultDictonary<K, V> = class(TObjectDictionary<K, V>)
private
M_DefaultValue : V;
public
constructor Create(Defaultvalue : V);
destructor Destroy; reintroduce;
function GetDefaultValue : V;
function TryGetValue(const Key: K; out Value: V): Boolean;
function GetValueOf(const Key: K) : V;
end;
implementation
//
// Contructor and destructor
//
constructor TDefaultDictonary<K, V>.Create(Defaultvalue : V);
begin
inherited Create;
M_DefaultValue := Defaultvalue;
end;
destructor TDefaultDictonary<K, V>.Destroy;
begin
inherited Destroy;
end;
//
// Get the default Value
//
function TDefaultDictonary<K, V>.GetDefaultValue : V;
begin
Result := M_DefaultValue;
end;
//
// Try to get a value from the dictionary for the given key.
//
// If the value is found then "Value" holds it and the function returns true.
// If the value is not found then "Value" holds the default value and the
// function returns false.
//
function TDefaultDictonary<K, V>.TryGetValue(const Key: K; out Value: V): Boolean;
var
IsKeyFound : boolean;
DictVal : V;
begin
IsKeyFound := inherited TryGetValue(Key, DictVal);
if not IsKeyFound then begin
DictVal := M_DefaultValue;
end;
// Outputs:
Value := DictVal;
Result := IsKeyFound;
end;
//
// Get a value from the dictionary for the given key.
//
// If the value is found then the function returns it.
// If the value is not found the function returns the default value.
//
function TDefaultDictonary<K, V>.GetValueOf(const Key: K) : V;
var
DictVal : V;
begin
TryGetValue(Key, DictVal);
Result := DictVal;
end;
测试如下:
unit Test_Utils;
{
Test the TDefaultDictionary functionality
}
interface
uses
Sysutils, Math, TestFramework, Util;
type
TestUtil = class(TTestCase)
public
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestDefaultDictionaryGetDefaultResponse;
procedure TestDefaultDictionaryExistingKey;
procedure TestDefaultDictionaryNotExistingKey;
end;
implementation
procedure TestUtil.SetUp;
begin
end;
procedure TestUtil.TearDown;
begin
end;
procedure TestUtil.TestDefaultDictionaryGetDefaultResponse;
var
dd : TDefaultDictonary<integer, string>;
begin
dd := TDefaultDictonary<integer, string>.Create('Default response');
checkEquals('Default response', dd.GetDefaultValue);
dd.Free;
end;
procedure TestUtil.TestDefaultDictionaryExistingKey;
var
dd : TDefaultDictonary<integer, string>;
outVal : string;
isKeyFound : boolean;
begin
dd := TDefaultDictonary<integer, string>.Create('Default response');
dd.Add(1, 'My one');
checkEquals(1, dd.Count,
'One element as count');
isKeyFound := dd.TryGetValue(1, outVal);
check(isKeyFound,
'Key not found by TryGetValue');
checkEquals('My one', outVal,
'Value given by TryGetValue');
checkEquals('My one', dd[1],
'Value given by indexing as array');
dd.Free;
end;
procedure TestUtil.TestDefaultDictionaryNotExistingKey;
var
dd : TDefaultDictonary<integer, string>;
outVal : string;
isKeyFound : boolean;
begin
dd := TDefaultDictonary<integer, string>.Create('Default response');
dd.Add(1, 'one');
isKeyFound := dd.TryGetValue(2, outVal);
check(not isKeyFound,
'Key should not be found by TryGetValue');
checkEquals('Default response', outVal,
'Default Value given by TryGetValue');
checkEquals('Default response', dd.GetValueOf(2),
'Default Value given by indexing as array');
//
// It is possible to oveload the indexer operator?
// Please review or delete me !
//
//checkEquals('Default response', dd[2],
// 'Value given by indexing as array');
//
dd.Free;
end;
initialization
RegisterTest(TestUtil.Suite);
end.
这远远没有完成。我也希望索引器运算符能够工作(请参见最后一个测试)。这是可能的吗?还需要实现什么?
这个实现是否泄漏了M_DefaultValue(我对Delphi不熟悉)。我不能在析构函数中做M_DefaultValue.Free(由于构造函数的限制,这并不太灵活)。应该怎么办?
提前致谢,
Francis