gentlejo
gentlejo

Reputation: 2710

How can I make multidimensional associative array in Delphi?

I want to make a data structure like multidimensional associative array in Delphi.

I know that there is TObjectDictionary. But making multidimensional array with TObjectDictionary is so hard and not efficient I think.

Is there any other good approach to make multidimensional associative array in Delphi?

Upvotes: 0

Views: 761

Answers (1)

Andrei Galatyn
Andrei Galatyn

Reputation: 3432

TDictionary is hash-based, so performance will not seriously degrade for any number of dimensions. Two-dimensional version of dictionary can be implementation like this:

  T2DimDictionary<TDim1,TDim2,TValue> = class
  private
    function GetValue(x: TDim1; y: TDim2): TValue;
    procedure SetValue(x: TDim1; y: TDim2; const Value: TValue);
  protected
    FDictionary: TObjectDictionary<TDim1, TDictionary<TDim2, TValue>>;
  public
    constructor Create;
    destructor Destroy; override;
    property Values[x: TDim1; y: TDim2]: TValue read GetValue write SetValue; default;
  end;

{ T2DimDictionary }

constructor T2DimDictionary<TDim1,TDim2,TValue>.Create;
begin
  FDictionary := TObjectDictionary<TDim1, TDictionary<TDim2, TValue>>.Create;
end;

destructor T2DimDictionary<TDim1,TDim2,TValue>.Destroy;
begin
  FreeAndNil(FDictionary);
  inherited;
end;

function T2DimDictionary<TDim1,TDim2,TValue>.GetValue(x: TDim1; y: TDim2): TValue;
var
  SubArray: TDictionary<TDim2, TValue>;
begin
  if not FDictionary.TryGetValue(x, SubArray) or
    not SubArray.TryGetValue(y, result)
  then
    raise exception.Create('Error');
end;

procedure T2DimDictionary<TDim1,TDim2,TValue>.SetValue(x: TDim1; y: TDim2;
  const Value: TValue);
var
  SubArray: TDictionary<TDim2, TValue>;
begin
  if not FDictionary.TryGetValue(x, SubArray) then
  begin
    SubArray := TDictionary<TDim2, TValue>.Create;
    FDictionary.Add(x, SubArray);
  end;
  SubArray.AddOrSetValue(y, Value);
end;

var
  d: T2DimDictionary<integer, string, string>;
begin
  d := T2DimDictionary<integer, string, string>.Create;
  d[1,'january'] := 'test1';
  d[1,'march'] := 'test2';
  assert(d[1,'january']='test1');
  FreeAndNil(d);
end;

Alternatively you can use single TDictionary with complex key based on all "dimensions".

Upvotes: 5

Related Questions