0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Delphiで0ベースの配列を1(任意)ベースの配列に偽装させる

Last updated at Posted at 2023-09-02

0ベースの配列を任意の開始Indexの配列に偽装させるクラス

TCustomBasedArray = class

TCustomBasedArray = record
にしてもそのまま動作します。
オブジェクトの開放コードが不要になるのでrecord型が推奨

CustomBasedArray.pas
unit CustomBasedArray;

interface

uses
  System.SysUtils;

type
  TEnumerator<T> = class;

  TCustomBasedArray<T> = class
  private
    FArray: TArray<T>;
    FStartIndex: Integer;
    FSize: Integer;
    function GetHigh: Integer;
    function GetItem(index: Integer): T;
    procedure SetItem(index: Integer; value: T);
  public
    constructor Create(Size, StartIndex: Integer); overload;
    //SourceArrayにTArray<T>型でも互換性あり
    constructor Create(const SourceArray: Array of T; StartIndex: Integer); overload;
    //for..in ループを使用してイテレーションできるようにする定義
    function GetEnumerator: TEnumerator<T>;
    property Length: Integer read FSize;
    property Low: Integer read FStartIndex;
    property High: Integer read GetHigh;
    // デフォルトプロパティで配列の要素へのアクセスをサポート
    property Items[index: Integer]: T read GetItem write SetItem; default;
  end;


  //for..in ループを使用してイテレーションできるようにするクラス
  TEnumerator<T> = class
  private
    FData: TCustomBasedArray<T>;
    FIndex: Integer;
    function GetCurrent: T;
  public
    constructor Create(const AData: TCustomBasedArray<T>);
    function MoveNext: Boolean;
    property Current: T read GetCurrent;
  end;

implementation

{ TCustomBasedArray<T> }
constructor TCustomBasedArray<T>.Create(Size, StartIndex: Integer);
begin
  FStartIndex := StartIndex;
  FSize := Size;
  SetLength(FArray, FSize);
end;

//既存の0ベースの動的配列を開始Indexを指定してコピーする
constructor TCustomBasedArray<T>.Create(const SourceArray: Array of T; StartIndex: Integer);
begin
  FStartIndex := StartIndex;
  FSize := System.Length(SourceArray);
  SetLength(FArray, FSize);
  for var i := System.Low(FArray) to System.High(FArray) do
    FArray[i] := SourceArray[i];
end;

function TCustomBasedArray<T>.GetHigh: Integer;
begin
  Result := FStartIndex + FSize - 1;
end;

function TCustomBasedArray<T>.GetItem(index: Integer): T;
begin
  Result := FArray[index - FStartIndex];
end;

procedure TCustomBasedArray<T>.SetItem(index: Integer; value: T);
begin
  FArray[index - FStartIndex] := value;
end;

function TCustomBasedArray<T>.GetEnumerator: TEnumerator<T>;
begin
  Result := TEnumerator<T>.Create(Self);
end;


{ TEnumerator<T> }
  //for..in ループを使用してイテレーションできるようにするクラス
constructor TEnumerator<T>.Create(const AData: TCustomBasedArray<T>);
begin
  FData := AData;
  FIndex := FData.Low - 1;
end;

function TEnumerator<T>.MoveNext: Boolean;
begin
  Inc(FIndex);
  Result := FIndex <= FData.High;
end;

function TEnumerator<T>.GetCurrent: T;
begin
  Result := FData[FIndex];
end;

end.

使用サンプル

record型にしたらオブジェクトのFreeは不要

procedure TForm1.Button1Click(Sender: TObject);
var
  arr: TCustomBasedArray<Integer>;
begin
  arr := TCustomBasedArray<Integer>.Create(10, -5);

  //要素に値を設定
  for var i := arr.Low to arr.High do
    arr[i] := i * 10;

  for var i := arr.Low to arr.High do
    OutputDebugFmt('Index: %d, 値: %d', [i,arr[i]]);

  //イテレータのテスト
  for var item in arr do
    OutputDebugFmt('値: %d', [item]);

  arr.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  arr: TCustomBasedArray<string>;
  StringArray: TArray<string>;
begin
  StringArray := TArray<string>.Create('山田','鈴木', '佐藤');

  //偽装クラスに開始Indexを指定してコピー
  arr := TCustomBasedArray<string>.Create(StringArray, 10);
  for var i := arr.Low to arr.High do
    OutputDebugFmt('Index: %d, 値: %s', [i,arr[i]]);

  arr.Free;
end;

ログの書き込みは、こちらで紹介した関数を使用しています

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?