在Delphi中使用具有多维动态数组的Length()

时间:2021-08-23 17:34:33

I am using a multi-dimensional dynamic array in delphi and am trying to figure this out:

我在delphi中使用多维动态数组,并试图解决这个问题:

I have 2 seperate values for the first index and second index that are totally seperate of each other.

对于第一个索引和第二个索引,我有两个完全独立的单独值。

As new values come I want to grow the array if that new value is outside of either bound.

当新值出现时,如果新值超出任何一个范围,我想增长数组。

For new values x, y

对于新值x,y

I check:

if Length(List) < (x + 1) then
   SetLength(List, x + 1);
if Length(List[0]) < (y + 1) then
   SetLength(List, Length(List), y + 1);

Is this the correct way to do this or is there a better way to grow the array as needed?

这是正确的方法吗?还是有更好的方法来根据需要增长数组?

3 个解决方案

#1


2  

I think you forgot to use the second index on the second dimension;

我想你忘了在第二维上使用第二个索引;

Your code should probably read like this :

您的代码应该如下所示:

if Length(List) < (x + 1) then
   SetLength(List, x + 1);
if Length(List[x]) < (y + 1) then
   SetLength(List[x], y + 1);

Note the use of 'x' as the first dimension index when growing the second dimension.

注意在增长第二维时使用'x'作为第一维索引。

One caution though :

但有一点需要注意:

You should be aware of the fact that Delphi uses reference-counting on dynamic arrays too (just like how it's done with AnsiString). Because of this, growing the array like above will work, but any other reference to it will still have the old copy of it!

您应该意识到Delphi也在动态数组上使用引用计数(就像使用AnsiString一样)。因此,像上面那样增长数组会起作用,但对它的任何其他引用仍然会有它的旧副本!

The only way around this, is keeping track of these array's with one extra level of indirection - ie. : Use a pointer to the dynamic array (which is also a pointer in itself, but that's okay).

解决这个问题的唯一方法就是用一个额外的间接级别跟踪这些数组 - 即。 :使用指向动态数组的指针(它本身也是一个指针,但没关系)。

Also note that any of those 'external' pointers should be updated in any situation that the address of the dynamic array could change, as when growing/shrinking it using SetLength().

另请注意,任何这些“外部”指针都应该在动态数组地址可能发生变化的任何情况下进行更新,例如使用SetLength()进行增长/缩小时。

#2


4  

It looks fine to me - if you change the last line to

它看起来很好 - 如果你改变最后一行

SetLength(List, Length(List), y + 1);

#3


1  

@PatrickvL: Sorry, but that is just plain wrong. Your code does not even compile because it tries to set two dimensions for the single-dimensional element List[x]. (PatrickvL updated his code so this part of the answer is no longer valid.)

@PatrickvL:对不起,但这是完全错的。您的代码甚至无法编译,因为它试图为一维元素List [x]设置两个维度。 (PatrickvL更新了他的代码,因此这部分答案不再有效。)

The following code demonstrates multidimensional array resizing.

以下代码演示了多维数组大小调整。

program TestDimensions;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  List: array of array of integer;

begin
  //set both dimensions
  SetLength(List, 3, 2);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 3, Y = 2
  //set main dimension to 4, keep subdimension untouched
  SetLength(List, 4);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 2
  //set subdimension to 3, keep main dimenstion untouched
  SetLength(List, Length(List), 3);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 3
  //all List[0]..List[3] have 3 elements
  Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //3333
  //you can change subdimension for each List[] vector
  SetLength(List[0], 1);
  SetLength(List[3], 7);
  //List is now a ragged array
  Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //1337
  //this does not even compile because it tries to set dimension that does not exist!
//  SetLength(List[0], Length(List[0]), 12);
  Readln;
end.

The Delphi help also explains this quite nicely (Structured Types, Arrays).

Delphi帮助也很好地解释了这一点(结构化类型,数组)。

Multidimensional Dynamic Arrays To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,

多维动态数组要声明多维动态数组,请使用迭代数组的......结构。例如,

type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;

type TMessageGrid = string数组的数组; var Msgs:TMessageGrid;

declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,

声明一个二维的字符串数组。要实例化此数组,请使用两个整数参数调用SetLength。例如,如果I和J是整数值变量,

SetLength(Msgs,I,J);

allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.

分配一个I-by-J数组,Msgs [0,0]表示该数组的一个元素。

You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example,

您可以创建非矩形的多维动态数组。第一步是调用SetLength,为数组的前n个维度传递参数。例如,

var Ints: array of array of Integer;
SetLength(Ints,10);

var Ints:Integer数组的数组; SetLength(整数,10);

allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example

为Ints分配十行但没有列。之后,您可以一次分配一个列(给它们不同的长度);例如

SetLength(Ints[2], 5);

makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2,4] := 6.

使Ints的第三列五个整数长。此时(即使尚未分配其他列),您可以将值分配给第三列 - 例如,Ints [2,4]:= 6。

The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.

以下示例使用动态数组(以及在SysUtils单元中声明的IntToStr函数)来创建字符串的三角形矩阵。

var
A : array of array of string;
I, J : Integer;
begin
SetLength(A, 10);
for I := Low(A) to High(A) do
begin
SetLength(A[I], I);
for J := Low(A[I]) to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;

var A:字符串数组的数组;我,J:整数;开始SetLength(A,10);对于I:=低(A)到高(A)确实开始SetLength(A [I],I);对于J:=低(A [I])到高(A [I])做A [I,J]:= IntToStr(I)+','+ IntToStr(J)+'';结束;结束;

#1


2  

I think you forgot to use the second index on the second dimension;

我想你忘了在第二维上使用第二个索引;

Your code should probably read like this :

您的代码应该如下所示:

if Length(List) < (x + 1) then
   SetLength(List, x + 1);
if Length(List[x]) < (y + 1) then
   SetLength(List[x], y + 1);

Note the use of 'x' as the first dimension index when growing the second dimension.

注意在增长第二维时使用'x'作为第一维索引。

One caution though :

但有一点需要注意:

You should be aware of the fact that Delphi uses reference-counting on dynamic arrays too (just like how it's done with AnsiString). Because of this, growing the array like above will work, but any other reference to it will still have the old copy of it!

您应该意识到Delphi也在动态数组上使用引用计数(就像使用AnsiString一样)。因此,像上面那样增长数组会起作用,但对它的任何其他引用仍然会有它的旧副本!

The only way around this, is keeping track of these array's with one extra level of indirection - ie. : Use a pointer to the dynamic array (which is also a pointer in itself, but that's okay).

解决这个问题的唯一方法就是用一个额外的间接级别跟踪这些数组 - 即。 :使用指向动态数组的指针(它本身也是一个指针,但没关系)。

Also note that any of those 'external' pointers should be updated in any situation that the address of the dynamic array could change, as when growing/shrinking it using SetLength().

另请注意,任何这些“外部”指针都应该在动态数组地址可能发生变化的任何情况下进行更新,例如使用SetLength()进行增长/缩小时。

#2


4  

It looks fine to me - if you change the last line to

它看起来很好 - 如果你改变最后一行

SetLength(List, Length(List), y + 1);

#3


1  

@PatrickvL: Sorry, but that is just plain wrong. Your code does not even compile because it tries to set two dimensions for the single-dimensional element List[x]. (PatrickvL updated his code so this part of the answer is no longer valid.)

@PatrickvL:对不起,但这是完全错的。您的代码甚至无法编译,因为它试图为一维元素List [x]设置两个维度。 (PatrickvL更新了他的代码,因此这部分答案不再有效。)

The following code demonstrates multidimensional array resizing.

以下代码演示了多维数组大小调整。

program TestDimensions;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  List: array of array of integer;

begin
  //set both dimensions
  SetLength(List, 3, 2);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 3, Y = 2
  //set main dimension to 4, keep subdimension untouched
  SetLength(List, 4);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 2
  //set subdimension to 3, keep main dimenstion untouched
  SetLength(List, Length(List), 3);
  Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 3
  //all List[0]..List[3] have 3 elements
  Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //3333
  //you can change subdimension for each List[] vector
  SetLength(List[0], 1);
  SetLength(List[3], 7);
  //List is now a ragged array
  Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //1337
  //this does not even compile because it tries to set dimension that does not exist!
//  SetLength(List[0], Length(List[0]), 12);
  Readln;
end.

The Delphi help also explains this quite nicely (Structured Types, Arrays).

Delphi帮助也很好地解释了这一点(结构化类型,数组)。

Multidimensional Dynamic Arrays To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,

多维动态数组要声明多维动态数组,请使用迭代数组的......结构。例如,

type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;

type TMessageGrid = string数组的数组; var Msgs:TMessageGrid;

declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,

声明一个二维的字符串数组。要实例化此数组,请使用两个整数参数调用SetLength。例如,如果I和J是整数值变量,

SetLength(Msgs,I,J);

allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.

分配一个I-by-J数组,Msgs [0,0]表示该数组的一个元素。

You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example,

您可以创建非矩形的多维动态数组。第一步是调用SetLength,为数组的前n个维度传递参数。例如,

var Ints: array of array of Integer;
SetLength(Ints,10);

var Ints:Integer数组的数组; SetLength(整数,10);

allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example

为Ints分配十行但没有列。之后,您可以一次分配一个列(给它们不同的长度);例如

SetLength(Ints[2], 5);

makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2,4] := 6.

使Ints的第三列五个整数长。此时(即使尚未分配其他列),您可以将值分配给第三列 - 例如,Ints [2,4]:= 6。

The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.

以下示例使用动态数组(以及在SysUtils单元中声明的IntToStr函数)来创建字符串的三角形矩阵。

var
A : array of array of string;
I, J : Integer;
begin
SetLength(A, 10);
for I := Low(A) to High(A) do
begin
SetLength(A[I], I);
for J := Low(A[I]) to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;

var A:字符串数组的数组;我,J:整数;开始SetLength(A,10);对于I:=低(A)到高(A)确实开始SetLength(A [I],I);对于J:=低(A [I])到高(A [I])做A [I,J]:= IntToStr(I)+','+ IntToStr(J)+'';结束;结束;