Reputation: 2206
I am using a multi-dimensional dynamic array in delphi and am trying to figure this out:
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
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?
Upvotes: 4
Views: 25150
Reputation: 26830
@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.)
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).
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;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(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
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,
var Ints: array of array of Integer;
SetLength(Ints,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
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.
The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.
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;
Upvotes: 1
Reputation: 4164
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.
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!
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().
Upvotes: 2
Reputation: 26830
It looks fine to me - if you change the last line to
SetLength(List, Length(List), y + 1);
Upvotes: 4