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