Инициализация массива Delphi - PullRequest
18 голосов
/ 20 февраля 2010

У меня сейчас есть это, и это отстой:

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, аналогичный тому, который я хочу?

Ответы [ 3 ]

24 голосов
/ 20 февраля 2010

Массивы записей могут быть инициализированы в константных выражениях:

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;
10 голосов
/ 20 февраля 2010

Ответ 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 также позволяет вам определять открытые массивы inline, и нет никакого дополнительного вызова конструктора для записи. Результат использует ваш оригинальный предложенный синтаксис, но с массивом, обернутым в вызов функции. Он будет работать во всех версиях 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;

Возможно, вы захотите использовать ответ Джерри просто для того, чтобы дать своим массивам точек значащие имена, которые могут помочь при отладке, и одно из восьми магических чисел в этих определениях точек неверно.


Наконец, заметка о том, что имел в виду Delphi, когда сказал, что «синтаксис [1, 2, 3, 4] может работать только для целых чисел». Этот синтаксис определяет set , а не массив. У вас не может быть набора значений записи, но вы можете иметь набор целых чисел. Побочным эффектом является то, что синтаксис для набора целых чисел такой же, как и синтаксис для открытого массива целых чисел. Я думаю, что Delphi использует контекст, чтобы выяснить, какой из них вы имеете в виду, но иногда он может догадаться неправильно.

4 голосов
/ 20 февраля 2010

Вы не можете, потому что вы не можете выразить в теле кода точку, в которой вы можете выразить это в разделе 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 и на других вещах, не только на этом
  • Вы можете легко расширить BlendDimensions для 3 (или более) измерений
  • ... но будьте осторожны, потому что в него включена копия. :-) С сегодняшними компьютерами слабым местом, безусловно, будет ваша рука. :-) Вы устанете печатать намного быстрее, пока время копирования не будет замечено.

НТН

...