Delphi中2D数组的索引运算符属性

时间:2016-06-02 22:12:29

标签: arrays delphi

我知道在Delphi中,当你想允许使用索引运算符[]时,你必须做类似的事情,

property Item[index: integer]: integer read GetData; default;

如何在Delphi中实现多维数组,以便允许使用类似的东西:

matrix := TMatrix<integer>.Create(3,3);
matrix[0][2] := 5;
WriteLn(matrix[0][2]);

2 个答案:

答案 0 :(得分:6)

你不能那样使用[][]。但您可以在单个属性中声明多个索引,例如:

type
  TMatrix<T> = class
  private
    function GetData(index1, index2: Integer): T;
    procedure SetData(index1, index2: Integer; value: T);
  public
    constructor Create(dim1, dim2: Integer);
    property Item[index1, index2: Integer]: T read GetData write SetData; default;
  end;

然后你可以这样做:

matrix := TMatrix<integer>.Create(3,3);
matrix[0, 2] := 5;
WriteLn(matrix[0, 2]);

答案 1 :(得分:1)

如果您愿意,可以使用[][]来访问元素。如果您的类型是一个数组(二维或锯齿状动态),那么这种访问元素的方法将被烘焙到该语言中。对于用户定义的类型,您需要实现它。

无法在用户定义类型的单个步骤中实现[][]。您需要做的是将过程分成两个独立的部分。第一部分是实现[]以返回矩阵的一行。然后在该行上实现[]以返回一个元素。这是一个例子:

type
  TMatrix<T> = class
  public
    type
      TRow = record
      private
        FMatrix: TMatrix<T>;
        FRowIndex: Integer;
        function GetItem(ColIndex: Integer): T; inline;
        procedure SetItem(ColIndex: Integer; const Value: T); inline;
      public
        property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
      end;
  private
    FData: TArray<TArray<T>>;
    function GetRow(RowIndex: Integer): TRow; inline;
  public
    constructor Create(RowCount, ColCount: Integer);
    property Rows[RowIndex: Integer]: TRow read GetRow; default;
  end;

{ TMatrix<T>.TRow }

function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
  Result := FMatrix.FData[FRowIndex, ColIndex];
end;

procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
  FMatrix.FData[FRowIndex, ColIndex] := Value;
end;

{ TMatrix<T> }

constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
  inherited Create;
  SetLength(FData, RowCount, ColCount);
end;

function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
  Result.FMatrix := Self;
  Result.FRowIndex := RowIndex;
end;

但是,虽然已经证明这是可能的,但我建议使用带有两个索引的array property更为惯用。这意味着您将使用M[Row,Col]而非M[Row][Col]访问矩阵。在所有语言中都找不到这个特定的成语(M[Row,Col]),因此您可能不熟悉它。支持可能如下所示:

type
  TMatrix<T> = class
  public
    type
      TRow = record
      private
        FMatrix: TMatrix<T>;
        FRowIndex: Integer;
        function GetItem(ColIndex: Integer): T; inline;
        procedure SetItem(ColIndex: Integer; const Value: T); inline;
      public
        property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
      end;
  private
    FData: TArray<TArray<T>>;
    function GetRow(RowIndex: Integer): TRow; inline;
    function GetItem(RowIndex, ColIndex: Integer): T; inline;
    procedure SetItem(RowIndex, ColIndex: Integer; const Value: T); inline;
  public
    constructor Create(RowCount, ColCount: Integer);
    property Rows[RowIndex: Integer]: TRow read GetRow;
    property Items[RowIndex, ColIndex: Integer]: T read GetItem write SetItem; default;
  end;

{ TMatrix<T>.TRow }

function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
  Result := FMatrix.FData[FRowIndex, ColIndex];
end;

procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
  FMatrix.FData[FRowIndex, ColIndex] := Value;
end;

{ TMatrix<T> }

constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
  inherited Create;
  SetLength(FData, RowCount, ColCount);
end;

function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
  Result.FMatrix := Self;
  Result.FRowIndex := RowIndex;
end;

function TMatrix<T>.GetItem(RowIndex, ColIndex: Integer): T;
begin
  Result := FData[RowIndex, ColIndex];
end;

procedure TMatrix<T>.SetItem(RowIndex, ColIndex: Integer; const Value: T);
begin
  FData[RowIndex, ColIndex] := Value;
end;

请注意,在此版本中,我们选择将Items作为默认属性。这意味着如果您想要访问一行,则必须明确命名Rows属性:M.Rows[RowIndex]