Me gustaría tener un diccionario que devuelve un valor predeterminado cuando no se encuentra la clave de búsqueda. Lectura de la documentación:Delphi Generics> Diccionario con valor predeterminado
Generics.Collections.Tdictionary [...] Esta clase proporciona [...] un mapeo y contenido inicial.
1 - ¿Cómo? ¿Hay alguna manera de hacerlo en Python: {1: 'uno'; 2: 'dos'}?
Generics.Collections.TDictionary.TryGetValue [...] TryGetValue devuelve verdadero si la clave dada está en el diccionario y proporciona su valor en Valor. De lo contrario, devuelve falso y Value se establece en el tipo de valor predeterminado de Tvalue.
2 - ¿Cómo puedo establecer este valor predeterminado? No puedo encontrar un constructor (puede ser que acabo de buscar en el lugar equivocado. Estoy esperando algo como "constructor Create (DefaultValue: TValue);")
Así que estoy tratando de implementar mi propio (puede ser que no es necesario Véase más arriba.): (comentarios y sugerencias son bienvenidos)
El código es:
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;
y las pruebas son:
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.
eso está lejos de siendo completo. Me gustaría que el operador del indexador también funcione (ver la última prueba). Es así de posible? ¿Qué debería también implementarse?
¿Esta implementación se filtra M_DefaultValue (soy nuevo en Delphi). No puedo hacer algo M_DefaultValue.Free en el destructor (no es tan flexible debido a la restricción del constructor) ¿Qué se puede hacer aquí?
Gracias de antemano,
Francis
Ha planteado una muy buena pregunta, ya que actualmente, en Delphi, tenemos que hacer dos búsquedas en el diccionario. Lo mismo es cierto acerca de PHP. –