Arrays

Dynamic arrays are reference types with reference counting — but not copy-on-write:

14.1 Static arrays

Any ordinal subrange can be an index type.

Grid[I, J] and Grid[I][J] are equivalent.

Static arrays are value types: assignment copies all elements; passing by value copies too.

Use Low, High, Length, and SizeOf instead of hard-coded bounds.

Enable {$R+} during development to catch out-of-range indexes.

var
  Scores: array[1..5] of Integer;
  Counts: array['a'..'z'] of Integer;            // index by Char
  Hours: array[TDay] of Double;                  // index by an enumeration
  Grid: array[0..2, 0..2] of Char;               // 2-D
  Cube: array[1..4, 1..4, 1..4] of Byte;         // 3-D
const
  Months: array[1..12] of string =
    ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
     'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
  Identity: array[0..1, 0..1] of Integer = ((1, 0), (0, 1));

14.2 Example: frequency count

program LetterFreq;
{$mode objfpc}{$H+}
var
  Counts: array['a'..'z'] of Integer;
  S: string;
  C: Char;
begin
  FillChar(Counts, SizeOf(Counts), 0);
  S := LowerCase('The quick brown fox jumps over the lazy dog');
  for C in S do
    if C in ['a'..'z'] then
      Inc(Counts[C]);
  for C := 'a' to 'z' do
    if Counts[C] > 1 then
      Writeln(C, ': ', Counts[C]);
end.

14.3 Dynamic arrays

Dynamic arrays are reference types with reference counting — but not copy-on-write:

var
  A: array of Integer;          // or: TArray<Integer> in Delphi / FPC delphi mode
  M: array of array of Double;  // jagged 2-D
  I: Integer;
begin
  SetLength(A, 5);              // indices 0..4, zero-initialized
  for I := 0 to High(A) do
    A[I] := I * I;
  SetLength(A, 10);             // grows; existing elements kept
  Writeln(Length(A));           // 10

  SetLength(M, 3, 4);           // rectangular 3x4
  M[2, 3] := 1.5;

  A := [5, 3, 8];               // array constructor (Delphi XE7+, FPC 3.2+)
  A := A + [13, 21];            // concatenation (Delphi XE7+; FPC 3.2 delphi mode or {$modeswitch arrayoperators})
  Insert(99, A, 1);             // insert 99 at index 1 (Delphi XE7+, FPC 3.2+)
  Delete(A, 0, 1);              // delete 1 element at index 0
  A := nil;                     // frees the array (same as SetLength(A, 0))
end.
var
  X, Y: array of Integer;
begin
  X := [1, 2, 3];
  Y := X;           // Y and X share the same data!
  Y[0] := 100;
  Writeln(X[0]);    // 100
  Y := Copy(X);     // independent copy (Copy(X, Start, Count) for a slice)
  Y[0] := 1;
  Writeln(X[0]);    // still 100
end.

14.4 Sorting and searching

Library alternatives: TArray.Sort<T> and TArray.BinarySearch<T> (Delphi System.Generics.Collections; FPC Generics.Collections provides TArrayHelper<T>), TList<T>.Sort, TStringList.Sort.

type
  TIntArray = array of Integer;

procedure InsertionSort(var A: array of Integer);
var
  I, J, Key: Integer;
begin
  for I := 1 to High(A) do
  begin
    Key := A[I];
    J := I - 1;
    while (J >= 0) and (A[J] > Key) do
    begin
      A[J + 1] := A[J];
      Dec(J);
    end;
    A[J + 1] := Key;
  end;
end;

function BinarySearch(const A: array of Integer; Target: Integer): Integer;
var
  Lo, Hi, Mid: Integer;
begin
  Lo := 0;
  Hi := High(A);
  while Lo <= Hi do
  begin
    Mid := Lo + (Hi - Lo) div 2;
    if A[Mid] = Target then Exit(Mid)
    else if A[Mid] < Target then Lo := Mid + 1
    else Hi := Mid - 1;
  end;
  Result := -1;
end;

14.5 Matrix example

type
  TMatrix = array[1..3, 1..3] of Double;

function Multiply(const A, B: TMatrix): TMatrix;
var
  I, J, K: Integer;
begin
  for I := 1 to 3 do
    for J := 1 to 3 do
    begin
      Result[I, J] := 0;
      for K := 1 to 3 do
        Result[I, J] := Result[I, J] + A[I, K] * B[K, J];
    end;
end;

14.6 Array summary

Open array parameter Size fixed at compile time no (SetLength) any ordinal range inline (stack/global/record) heap, ref-counted caller's storage array[a..b, c..d] array of array of T one dimension only