2010-10-23 35 views
5

Tôi muốn có từ điển trả về giá trị mặc định khi không tìm thấy khóa tìm kiếm. Đọc từ tài liệu:Delphi Generics> Từ điển với giá trị mặc định

Generics.Collections.Tdictionary […] Lớp này cung cấp ánh xạ […] và nội dung ban đầu.

1 - Làm cách nào? Có cách nào để làm điều đó ala Python: {1: ‘one’; 2: ’hai’}?

Generics.Collections.TDictionary.TryGetValue [...] TryGetValue trả về true nếu khóa đã cho nằm trong từ điển và cung cấp giá trị của nó trong Giá trị. Nếu không, nó trả về false và Value được đặt thành kiểu giá trị mặc định của Tvalue.

2 - Làm cách nào tôi có thể đặt giá trị mặc định này? Tôi không thể tìm thấy một nhà xây dựng (có thể là tôi vừa tìm kiếm ở nơi sai. Tôi đang mong đợi một cái gì đó như "constructor Create (DefaultValue: TValue);")

Vì vậy, tôi đang cố gắng thực hiện của riêng tôi (có thể là không cần thiết Xem ở trên.): (! đánh giá và đề nghị được hoan nghênh)

mã này là:

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; 

và các bài kiểm tra bao gồm:

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. 

Đó là xa hoàn thành. Tôi muốn có toán tử lập chỉ mục làm việc (xem thử nghiệm cuối cùng). Điều đó là có thể? Điều gì cần được triển khai?

Triển khai này có rò rỉ M_DefaultValue (Tôi mới đến Delphi) hay không. Tôi không thể làm một cái gì đó M_DefaultValue.Free trong destructor (không phải là quá linh hoạt do hạn chế constructor) Điều gì có thể được thực hiện ở đây?

Cảm ơn trước,

Francis

+0

Bạn đã nêu ra một câu hỏi rất hay, vì hiện tại, ở Delphi, chúng tôi phải thực hiện hai tra cứu từ điển. Điều này cũng đúng về PHP. –

Trả lời

1

Trước khi viết tất cả các mã này chính mình, bạn có thể muốn nhìn vào lớp học chung trong DeHL library.

Nó hỗ trợ này:

Loại Hỗ trợ khái niệm rằng định nghĩa một tập vỡ nợ "các lớp học hỗ trợ" cho mỗi built-in loại Delphi (sử dụng như giá trị mặc định trong bộ sưu tập). Tùy chỉnh "loại hỗ trợ" các lớp học có thể được đăng ký cho các loại dữ liệu tùy chỉnh của bạn.

--jeroen

+0

Tôi hy vọng đó là một cái gì đó khác nhau: so sánh mặc định và tương tự, không phải là một giá trị mặc định trả về từ một từ điển trong trường hợp "chìa khóa không hiện diện". –

+0

Câu trả lời của bạn không thân thiện. Ý tưởng chính của câu hỏi của tác giả là để tránh hai tra cứu: tra cứu đầu tiên không kiểm tra xem giá trị có tồn tại hay không, và lần tra cứu thứ hai để trả về giá trị. Nếu bạn đã cung cấp một câu trả lời rõ ràng đơn giản, với ví dụ mã, điều này sẽ hữu ích, ví dụ về cách sử dụng TryGetValue và mỗi loại có giá trị mặc định không thể thay đổi, ví dụ, Integer có 0, chuỗi '', vv –

+0

@MaximMasiutin như francis người dùng không bao giờ trả lời (lần cuối cùng hoạt động trong năm 2010) và đưa ra một số câu hỏi trong một câu hỏi SO, rất khó để hiểu những gì stumbleblock của mình là. Vì vậy, - cho nhà nước của mã trong câu hỏi - tôi giả định viết mã thư viện ổn định tốt là vấn đề lớn và trực tiếp đến - sau đó hiện tại - thư viện DeHL. Ngày nay tôi sẽ hướng đến http://spring4d.org –

0

Vấn đề chính là GetItem không phải là ảo trong TDictionary <>. Điều này có thể được giải quyết bằng cách chỉ cần thêm

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

vào lớp học của bạn.

Btw, destructors nên được overriden, không được giới thiệu lại vì vậy khi bạn lưu trữ nó trong một biến được định nghĩa là lớp phân cấp cao hơn nó gọi là destructor đúng. Đó chỉ là một thực hành tốt nhất, nhưng trong trường hợp cụ thể này, Items [] sẽ không hoạt động như bạn muốn nếu bạn làm điều đó.

Xin Chúa ban phước cho bạn.

Các vấn đề liên quan