Hola hace unos días hice esta implementación para simular un objeto de tipo Dictionary como en C#. He intentado hacerlo con TObject en vez de Variant, pero no me deja asignar directamente tipos primitivos como integer, etc. como sí me deja el tipo Variant.
¿Cambiaríais algo para que esté más optimizado? ¿Cuando en el clear hago los SetLength de nuevo a 0, que pasa con lo que había, se queda como basura en memoria?
Bueno gracias por las respuestas, aquí os dejo el código. Quien quiera usarlo lo puede usar.
Código Delphi
[-]unit uColecciones;
interface
uses Classes,Sysutils;
type
EKeyNotFound = class(Exception);
EKeyConflict = class(Exception);
TKeys = array of string;
TItems = array of Variant;
TDictionary = class
private
_count:integer;
_keys:TKeys;
_items:TItems;
function GetItem (Index:String):Variant;
procedure SetItem (Index:String; Value:Variant);
public
property Items[Index:String]:Variant read GetItem write SetItem; default;
procedure Add(key:string;item:Variant);
procedure Remove(key:string);
procedure Clear;
function Count:Integer;
function GetKeys:TKeys;
function GetItems:TItems;
constructor Create;
function KeyExists (Key:String):boolean;
function IndexOf (Key:String):Integer;
end;
implementation
procedure TDictionary.Add(key:string;item:Variant);
begin
if KeyExists(key) then
begin
raise EKeyConflict.Create('La clave ya existe.');
exit;
end
else
begin
inc(_count);
SetLength(_keys,_count);
SetLength(_items,_count);
_keys[count-1]:=key;
_items[count-1]:=item;
end;
end;
procedure TDictionary.Clear;
begin
SetLength(_keys,0);
SetLength(_items,0);
_count:=0;
end;
function TDictionary.Count: Integer;
begin
result:=_count;
end;
constructor TDictionary.Create;
begin
inherited;
_count:=0;
end;
function TDictionary.GetItem(Index: String): Variant;
var i,j:integer;
begin
if not KeyExists(Index) then
begin
raise EKeyNotFound.Create('Clave no encontrada.');
exit;
end
else
begin
j:=-1;
for i := 0 to _count - 1 do
if _keys[i]=index then
begin
j:=i;
break;
end;
end;
result:=_items[j];
end;
function TDictionary.GetItems: TItems;
begin
result:=_items;
end;
function TDictionary.GetKeys: TKeys;
begin
result:=_keys;
end;
function TDictionary.IndexOf(Key: String): Integer;
var i:integer;
begin
for i := 0 to _count - 1 do
if _keys[i]=key then
begin
result:=i;
exit;
end;
result:=-1;
end;
function TDictionary.KeyExists(Key: String): boolean;
var i:integer;
begin
for i := 0 to _count - 1 do
if _keys[i]=key then
begin
result:=true;
exit;
end;
result:=false;
end;
procedure TDictionary.Remove(Key:string);
var
i,j:integer;
ky:TKeys;
it:TItems;
begin
j:=IndexOf(Key);
if j=-1 then
begin
raise EKeyNotFound.Create('Clave no encontrada.');
exit;
end
else
begin
for i := 0 to _count - 1 do
if i<>j then
begin
SetLength(ky,Length(ky)+1);
SetLength(it,Length(it)+1);
ky[Length(ky)-1]:=_keys[i];
it[Length(it)-1]:=_items[i];
end;
dec(_count);
_keys:=ky;
_items:=it;
end;
end;
procedure TDictionary.SetItem(Index: String; Value:Variant);
var j:integer;
begin
j:=IndexOf(Index);
if j=-1 then
begin
raise EKeyNotFound.Create('Clave no encontrada.');
exit;
end
else
begin
_items[j]:=Value;
end;
end;
end.