Подтвердить что ты не робот

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

4b9b3361

Ответ 1

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

Ответ 2

Plainth 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, тогда как синтаксис "Создать" выше достаточно новый.

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

Ответ 3

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

НТН