2010-10-23 25 views
5

我想有一個字典,當找不到搜索關鍵字時返回默認值。從文檔中讀取:德爾福泛型>字典默認值

Generics.Collections.Tdictionary [...]該類提供了映射和初始內容。

1 - 如何?有沒有辦法做到這一點Python:{1:'one'; 2:'two'}?

Generics.Collections.TDictionary.TryGetValue [...] TryGetValue返回true,如果給定的鍵在字典中並在Value中提供其值。否則,它返回false,並將Value設置爲Tvalue的默認值類型。

2 - 如何設置此默認值?我找不到一個構造函數(可能是我剛纔在錯誤的地方搜索過的,我期待類似於「構造函數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(由於構造函數約束不太靈活)可以在這裏做什麼?

由於提前,

弗朗西斯

+0

您提出了一個非常好的問題,因爲目前在Delphi中,我們必須做兩個字典查找。關於PHP也是如此。 – 2017-05-16 00:52:46

回答

1

以前自己寫的所有代碼,你可能想看看在DeHL library通用類。

它支持這樣的:

限定 組默認的「支持類」的每個 內置在Delphi類型(在集合用作 的缺省值)

類型支持的概念。自定義「類型 支持」類可以註冊爲 您的自定義數據類型。

--jeroen

+0

我認爲這是不同的:默認比較器之類的,而不是從「字典」返回的「鍵不存在」的情況下返回的默認值。 – 2010-10-24 00:15:32

+0

你的回覆並不友善。作者的問題主要想法是避免兩次查找:第一次查找不檢查值是否存在,第二次查找實際返回值。如果您提供了一個明確的直接回復,並帶有代碼示例,那麼這將非常有用,例如關於如何使用TryGetValue以及每種類型具有不能更改的默認值,例如Integer具有0,string具有''等 – 2017-05-16 01:01:47

+0

@MaximMasutin因爲用戶francis從未迴應(上次在2010年活躍),並在一個SO問題中提出了一些問題,很難理解他的絆腳石是什麼。因此 - 考慮到問題中代碼的狀態 - 我認爲編寫好的穩定庫代碼是主要問題,並直接指向當時的DeHL庫。現在我將直接訪問http://spring4d.org – 2017-05-16 11:08:15

0

的主要問題是的GetItem不是虛擬在TDictionary <>。 這可以通過只添加

property Items[const Key: K]: V read GetValueOf write SetItem; default; 

到您的班級。

順便說一句,應該重寫析構函數,而不是重新引入,所以當你將它存儲在一個定義爲更高層次類的變量中時,它會調用正確的析構函數。這只是一種最佳做法,但在這種特定情況下,如果您這樣做,則Items []不會按照您的要求工作。

上帝保佑你。