我有一个包含多个变量的函数 f
(例如 3 个变量 f(x,y,z)
)。我想计算每个变量范围的函数结果并将它们存储在列表中。对于 3 个变量,这可能看起来像这样:
procedure LoopOver3Dimensions;
type
TListItem=record
x, y, z: Real;
CalculationResult: Real;
end;
var
List: TList<TListItem>;
NewListItem: TListItem;
i, j, k: Integer;
x, y, z: Real;
xStart, yStart, zStart: Real;
xEnd, yEnd, zEnd: Real;
NumberOfValuesToCalculateForDimension0: Integer;
NumberOfValuesToCalculateForDimension1: Integer;
NumberOfValuesToCalculateForDimension2: Integer;
begin
//set xStart, xEnd, NumberOfValuesToCalculateForDimension0 etc here
for i := 0 to NumberOfValuesToCalculateForDimension0 do
begin
x:=xStart+i*Abs(xEnd-xStart)/(NumberOfValuesToCalculateForDimension0-1);
for j := 0 to NumberOfValuesToCalculateForDimension1 do
begin
y:=yStart+j*Abs(yEnd-yStart)/(NumberOfValuesToCalculateForDimension1-1);
for k := 0 to NumberOfValuesToCalculateForDimension2 do
begin
z:=zStart+k*Abs(zEnd-zStart)/(NumberOfValuesToCalculateForDimension2-1);
NewListItem.x:=x;
NewListItem.y:=y;
NewListItem.z:=z;
NewListItem.CalculationResult:=DoCalculation(x, y, z);
List.Add(NewListItem);
end;
end;
end;
end;
我当然可以用相同的方式对超过 3 个维度(例如 20 个维度)进行编程,但这会变得非常麻烦,而且由于所有内容都是硬编码的,我无法在运行时更改维度的数量。
执行此操作的最佳方法是什么?
最佳答案
正如评论中所讨论的,为了支持任意数量的参数,最好使用可变长度的数组而不是参数。这是因为该语言对可变长度参数列表没有很好的支持。
一旦将所有参数打包为一个数组,您就会面临生成所有可能组合的问题。这不是一项完全简单的任务。我将不使用实际值,而是向您展示如何使用整数值的每个维度执行此操作,范围为 0
到 N[i]-1
,其中 i
是维度索引。一旦您可以迭代所有此类组合,您就可以轻松地扩展到生成您的实际值。
基本概念是维护当前迭代值,该值是递增的。第一维是循环的最里面。当它达到最大值时,它返回到零并且下一个外部维度增加。等等。下面是一些示例代码:
{$APPTYPE CONSOLE}
uses
System.SysUtils;
procedure IterMultiDim(const N: array of Integer; const Proc: TProc<TArray<Integer>>);
var
dim: Integer;
Current: TArray<Integer>;
begin
SetLength(Current, Length(N));
while Current[high(N)]<N[high(N)] do begin
Proc(Current);
// increment state
dim := 0;
while dim<=high(N) do begin
inc(Current[dim]);
if Current[dim]=N[dim] then begin
if dim<high(N) then begin
Current[dim] := 0;
end;
end else begin
break;
end;
inc(dim);
end;
end;
end;
procedure WriteIntArray(Arr: TArray<Integer>);
var
i: Integer;
begin
for i := 0 to high(Arr) do begin
Write(Arr[i]);
if i<high(Arr) then begin
Write(', ');
end;
end;
Writeln;
end;
procedure Main;
begin
IterMultiDim([2, 3, 4], WriteIntArray);
end;
begin
try
Main;
except
on E: Exception do begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
Readln;
end.
输出:
0, 0, 0 1, 0, 0 0, 1, 0 1, 1, 0 0, 2, 0 1, 2, 0 0, 0, 1 1, 0, 1 0, 1, 1 1, 1, 1 0, 2, 1 1, 2, 1 0, 0, 2 1, 0, 2 0, 1, 2 1, 1, 2 0, 2, 2 1, 2, 2 0, 0, 3 1, 0, 3 0, 1, 3 1, 1, 3 0, 2, 3 1, 2, 3
这项技术可以用多种方式进行总结。例如,它可以封装在一个 for/in 枚举器中,这样可以提高可读性。
关于algorithm - 遍历多个维度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44096698/