18

私は現在これを持っていますが、それはひどいです:

type TpointArray = array [0..3] of Tpoint;

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin

  Result[0] := point(1, 1);
  Result[1] := point(1, 2);
  Result[2] := point(1, 1);
  Result[3] := point(1, 1);
end;

しかし、代わりに、私はこのようなことをしたい:

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin
   Result := [Point(1,1), Point(1,2), Point(1,1), Point(1,1)];
end;

ただし、コンパイル時に、[1、2、3、4] 構文は整数に対してのみ機能すると不平を言います。

私が望む方法と同様に、Tpointの配列をインスタンス化/初期化する方法はありますか?

4

3 に答える 3

25

レコードの配列は、const 式で初期化できます。

const
  Points : TPointArray = ((X: 1; Y: 1), (X:1; Y:2), (X:1; Y:1), (X:1; Y:1));

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin
   Result := Points;
end;

XE7 では、次のようにレコードの動的配列を埋めることができます。

function GetPointArray: TArray<TPoint>;
begin
  Result := [Point(1,1),Point(1,2),Point(1,1),Point(1,1)];
end;
于 2010-02-20T04:44:27.110 に答える
10

Plainth's answerは、動的配列のコンストラクターに似た構文を示しています。これを TPoint 配列で直接使用して、はるかに単純なヘルパー関数を生成できます。

type
  TPointDynArray = array of TPoint;
  T4PointArray = array[0..3] of TPoint;

function PointDynArrayTo4PointArray(const input: TPointDynArray): T4PointArray;
var
  i: Integer;
begin
  Assert(Length(input) = Length(Result));
  for i := 0 to High(input) do
    Result[i] := input[i];
end;

class function rotationTable.offsets(pType, rotState, dir: integer): T4PointArray;
begin
  // New dynamic-array-constructor syntax here
  Result := PointDynArrayTo4PointArray(TPointDynArray.Create(
    Point(1,1), Point(1,2), Point(1,1), Point(1,1)));
end;

しかし、それはやり過ぎです。Delphi では、オープン配列をインラインで定義することもでき、追加のコンストラクタ呼び出しを記述する必要はありません。結果は元の提案された構文を使用しますが、配列は関数呼び出し内にラップされています。これは Delphi のすべてのバージョンで機能しますが、上記の「Create」構文はかなり新しいものです。

function PointOpenArrayTo4PointArray(const input: array of TPoint): T4PointArray;
var
  i: Integer;
begin
  Assert(Length(input) = Length(Result));
  for i := 0 to High(input) do
    Result[i] := input[i];
end;

class function rotationTable.offsets(pType, rotState, dir: integer): T4PointArray;
begin
  Result := PointOpenArrayTo4PointArray(
    [Point(1,1), Point(1,2), Point(1,1), Point(1,1)]);
end;

ポイントの配列に意味のある名前を付けるためだけにGerry の回答を使用することを検討することをお勧めします。これは、デバッグ時に役立ち、それらのポイント定義の 8 つのマジック ナンバーの 1 つが間違っている場合に役立ちます。


最後に、「[1, 2, 3, 4] 構文は整数に対してのみ機能する」という Delphi の意味についてのメモです。その構文は、配列ではなくsetを定義します。レコード値のセットを持つことはできませんが、整数のセットを持つことはできます。副作用として、一連の整数の構文は整数のオープン配列の構文と同じです。Delphi はコンテキストを使用して、どちらを意味するかを判断すると思いますが、間違った推測をする場合があります。

于 2010-02-20T15:25:58.970 に答える
4

セクションで表現できる方法でポイントをコード本体で表現できないため、できませんconst

ただし、特に妥当な数のポイントを持っている場合は、生活を楽にするためにいくつかのトリックを行うことができます.

次のような簡単な手順を実装できます (コードはテストされていません)。

procedure BlendDimensions(aXArray, aYArray: TIntegerDynArray; var aResult: TPointArray);
var
  nCount: integer;
  i: integer;

begin
  nCount:=High(aXArray);
  if nCount <> High(aYArray) then 
    Exception.Create('The two dimension arrays must have the same number of elements!');

  SetLength(aResult, nCount);
  for i:=0 to nCount do
  begin
    aResult[i].X:=aXArray[i]; //simple copy
    aResult[i].y:=aYArray[i];
  end;
end;

...ここで、TIntegerDynArray は RTL の整数の動的配列です。(実際、どの動的配列でも機能します)。また、上記の例の TPointArray も動的です。

したがって、あなたの仕事をするために、次のようにすることができます:

procedure Foo;
var
  myXCoords, myYCoords: TIntegerDynArray; //temp arrays
  myPoints: TPointArray; //this is the real thing

begin
  myXCoords:=TIntegerDynArray.Create( 1, 2, 3, 4, 5, 6, 7, 8, 9,10);
  myYCoords:=TIntegerDynArray.Create(21,32,34,44,55,66,65,77,88,92); //...for example 
  BlendDimensions(myXCoords, myYCoords, myPoints); //build the real thing
 //use it...
end;

注意事項:

  • あなたはあなたのポイントがはっきりとわかります
  • このようにして、非常に生産的になることができます
  • BlendDimensionsこれだけでなく他のものにも使えます
  • BlendDimensions3 つ (またはそれ以上) の次元に簡単に拡張できます
  • ...しかし、コピーが含まれているため注意してください。:-) 今日の PC では、弱点は圧倒的にあなたの手です。:-) コピーの時間が気になるまでは、もっと速くタイプするのに疲れるでしょう。

HTH

于 2010-02-20T07:46:30.463 に答える