Инициализация массива Delphi

В настоящее время у меня есть это, и это отстой:

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 ответа

Массивы записей могут быть инициализированы в выражениях 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;

Ответ Плейнта демонстрирует синтаксис, подобный конструктору, для динамических массивов. Вы можете использовать это непосредственно в массиве 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, в то время как приведенный выше синтаксис "Создать" довольно новый.

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] может работать только для целых чисел". Этот синтаксис определяет набор, а не массив. Вы не можете иметь набор значений записей, но вы можете иметь набор целых чисел. Побочным эффектом является то, что синтаксис для набора целых чисел такой же, как синтаксис для открытого массива целых чисел. Я думаю, что Delphi использует контекст, чтобы выяснить, какой из них вы имеете в виду, но иногда он может догадаться неправильно.

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

НТН

Другие вопросы по тегам