Delphi 带有 tlist 的动态数组
Delphi dynamic array with tlist
我正在 Delphi/Lazarus 中为类似于 BASIC 的语言创建一个简单的解释器。
我已经实现了很多功能。此时此刻,我正在尝试创建一个类似 DIM 的命令来处理多维数值数组。
我的想法是使用 TList 模拟仅受可用内存限制的多维数组。例如,当在我的解释器中声明如下命令时:
昏暗 num_arr[3,3,3]
我想创建一个双精度的三维数组,每个索引从 0 到 2 不等。
到目前为止,我只有创建 "TList array" 的功能。我使用两个 TList 对象来保存数组维度和数据项列表,我有第三个对象保存 store/retrieve 数据的索引。我想不通的是如何将索引列表关联到 TList 中的特定条目。当数组达到二维时很简单,我可以将每对索引转换为数字序列,但对三维和更多维度没有成功。
有什么算法可以用来解决这个问题吗?真的很难找到与那件事相关的东西。
欢迎任何有关如何实施类似内容的建议。下面我发布了到目前为止我开发的部分代码:
//Creates a "n" dimensional array
function array_allocate(Dim: TList; var DataArray: TList): integer;
var
i: integer;
s: string;
begin
Result := 1;
//Simple way to find the array length
//For example. An array with dimensions [3,3,3] will handle 27 items
for i := 0 to Dim.Count-1 do
begin
Result := Result * Integer(Dim[i]);
end;
Result := Result;
DataArray.Capacity := Result; //DataArray now handles 27 items
//************************************
//Every line below is just for testing
//************************************
fmMain.Memo1.Lines.Add('Allocating size for array with '+IntToStr(Dim.Count)+' dimension(s).');
s := '';
for i := 0 to Dim.Count-1 do
s := s + '['+IntToStr(Integer(Dim[i]))+']';
fmMain.Memo1.Lines.Add('DIM Sizes: '+s);
fmMain.Memo1.Lines.Add('Manage: '+IntToStr(Result)+' Items.');
end;
{*************************************}
{NOT functional, this is the challenge}
{*************************************}
function calculate_offset(Dim, Indexes: TList; var DataArray: TList; BaseAddr: integer): integer;
var
i, Depth, dimIdx: Integer;
k,index,sizeProduct: integer;
begin
for Depth := 0 to Dim.Count-1 do
for dimIdx := 0 to Integer(Dim[Depth])-1 do
fmMain.mmOut.Lines.Add('Dim: '+IntToStr(Depth)+' ,Index: '+IntToStr(dimIdx));
result := 0;
end;
procedure TfmMain.FormShow(Sender: TObject);
var
dataList: TList; //keep the data
dimList: TList; //keep the dimensions
indexList: TList; //keep the indexes
offset: integer;
begin
dimList := TList.Create; //create the dim array
//simulate the creation of an array with dimension [3,3,3]
//something like DIM myVar[3,3,3]
dimList.Add(Pointer(3));
dimList.Add(Pointer(3));
dimList.Add(Pointer(3));
dataList := TList.Create; //create the data list
array_allocate(dimList, dataList); //allocates memory
//indexList is the way to indicate which index to retrieve/store data
indexList := TList.Create;
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
//The idea is to relate indexes like [0,0,0], [0,0,1], [0,1,1] to
//a numeric sequence between 0 to 26 in this case (DIM = [3,3,3])
offset := calculate_offset(dimList, indexList, dataList, 1, 0);
indexList.Free;
dimList.Free;
dataList.Free;
end;
当我读到你的问题时,你想从一个索引元组转换为一个线性索引,假设行主要存储。
假设维度保存在动态数组 dim
中,索引保存在动态数组 idx
中。那么线性指数是这样计算的:
function LinearIndex(const dim, idx: array of Integer): Integer;
var
i: Integer;
begin
Assert(Length(dim)=Length(idx));
Assert(Length(dim)>0);
Result := idx[0];
for i := 1 to high(dim) do
Result := Result*dim[i-1] + idx[i];
end;
上述 LinearIndex 函数不适用于某些不平衡数组。例如,如果我正确地分配 "dim" 来保存值 [2,3],该函数将 return 2 作为 "idx" 的两个内容的索引:[0,2], [1,0]。
我根据我在 Whosebug 上找到的 another post 创建了一个 Pascal 函数,这个函数似乎有效。
function LinearIndex2(const dim, idx: array of Integer): Integer;
var
i,index,mult: Integer;
begin
Assert(Length(dim)=Length(idx));
Assert(Length(dim)>0);
index := 0; mult := 1;
for i := 0 to High(dim) do
begin
index := index + idx[i] * mult;
mult := mult * dim[i];
end;
result := index;
end;
我正在 Delphi/Lazarus 中为类似于 BASIC 的语言创建一个简单的解释器。 我已经实现了很多功能。此时此刻,我正在尝试创建一个类似 DIM 的命令来处理多维数值数组。 我的想法是使用 TList 模拟仅受可用内存限制的多维数组。例如,当在我的解释器中声明如下命令时:
昏暗 num_arr[3,3,3]
我想创建一个双精度的三维数组,每个索引从 0 到 2 不等。
到目前为止,我只有创建 "TList array" 的功能。我使用两个 TList 对象来保存数组维度和数据项列表,我有第三个对象保存 store/retrieve 数据的索引。我想不通的是如何将索引列表关联到 TList 中的特定条目。当数组达到二维时很简单,我可以将每对索引转换为数字序列,但对三维和更多维度没有成功。 有什么算法可以用来解决这个问题吗?真的很难找到与那件事相关的东西。 欢迎任何有关如何实施类似内容的建议。下面我发布了到目前为止我开发的部分代码:
//Creates a "n" dimensional array
function array_allocate(Dim: TList; var DataArray: TList): integer;
var
i: integer;
s: string;
begin
Result := 1;
//Simple way to find the array length
//For example. An array with dimensions [3,3,3] will handle 27 items
for i := 0 to Dim.Count-1 do
begin
Result := Result * Integer(Dim[i]);
end;
Result := Result;
DataArray.Capacity := Result; //DataArray now handles 27 items
//************************************
//Every line below is just for testing
//************************************
fmMain.Memo1.Lines.Add('Allocating size for array with '+IntToStr(Dim.Count)+' dimension(s).');
s := '';
for i := 0 to Dim.Count-1 do
s := s + '['+IntToStr(Integer(Dim[i]))+']';
fmMain.Memo1.Lines.Add('DIM Sizes: '+s);
fmMain.Memo1.Lines.Add('Manage: '+IntToStr(Result)+' Items.');
end;
{*************************************}
{NOT functional, this is the challenge}
{*************************************}
function calculate_offset(Dim, Indexes: TList; var DataArray: TList; BaseAddr: integer): integer;
var
i, Depth, dimIdx: Integer;
k,index,sizeProduct: integer;
begin
for Depth := 0 to Dim.Count-1 do
for dimIdx := 0 to Integer(Dim[Depth])-1 do
fmMain.mmOut.Lines.Add('Dim: '+IntToStr(Depth)+' ,Index: '+IntToStr(dimIdx));
result := 0;
end;
procedure TfmMain.FormShow(Sender: TObject);
var
dataList: TList; //keep the data
dimList: TList; //keep the dimensions
indexList: TList; //keep the indexes
offset: integer;
begin
dimList := TList.Create; //create the dim array
//simulate the creation of an array with dimension [3,3,3]
//something like DIM myVar[3,3,3]
dimList.Add(Pointer(3));
dimList.Add(Pointer(3));
dimList.Add(Pointer(3));
dataList := TList.Create; //create the data list
array_allocate(dimList, dataList); //allocates memory
//indexList is the way to indicate which index to retrieve/store data
indexList := TList.Create;
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
indexList.Add(Pointer(1));
//The idea is to relate indexes like [0,0,0], [0,0,1], [0,1,1] to
//a numeric sequence between 0 to 26 in this case (DIM = [3,3,3])
offset := calculate_offset(dimList, indexList, dataList, 1, 0);
indexList.Free;
dimList.Free;
dataList.Free;
end;
当我读到你的问题时,你想从一个索引元组转换为一个线性索引,假设行主要存储。
假设维度保存在动态数组 dim
中,索引保存在动态数组 idx
中。那么线性指数是这样计算的:
function LinearIndex(const dim, idx: array of Integer): Integer;
var
i: Integer;
begin
Assert(Length(dim)=Length(idx));
Assert(Length(dim)>0);
Result := idx[0];
for i := 1 to high(dim) do
Result := Result*dim[i-1] + idx[i];
end;
上述 LinearIndex 函数不适用于某些不平衡数组。例如,如果我正确地分配 "dim" 来保存值 [2,3],该函数将 return 2 作为 "idx" 的两个内容的索引:[0,2], [1,0]。 我根据我在 Whosebug 上找到的 another post 创建了一个 Pascal 函数,这个函数似乎有效。
function LinearIndex2(const dim, idx: array of Integer): Integer;
var
i,index,mult: Integer;
begin
Assert(Length(dim)=Length(idx));
Assert(Length(dim)>0);
index := 0; mult := 1;
for i := 0 to High(dim) do
begin
index := index + idx[i] * mult;
mult := mult * dim[i];
end;
result := index;
end;