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