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 的回答演示了动态数组的类似构造函数的语法。您可以直接在 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 版本,而上面的“创建”语法是相当新的。

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 的答案只是为您的点数组提供有意义的名称,这在调试时可能会有所帮助,并且这些点定义中的八个幻数之一是错误的。


最后,关于 Delphi 所说的“[1, 2, 3, 4] 语法只能用于整数”的注释。该语法定义了一个集合,而不是一个数组。你不能有一组记录值,但你可以有一组整数。副作用是一组整数的语法与开放整数数组的语法相同。我认为 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,到目前为止,弱点将是你的手。:-) 你会厌倦更快地打字,直到复制时间被注意到。

高温高压

于 2010-02-20T07:46:30.463 回答