Skip to content

TMultiArray

Ivan Semenkov edited this page Oct 10, 2021 · 1 revision

Table of contents

About

TMultiArray is a generic array of array of T which automatically increase in size. It is based on pascal's dynamic array structures. TMultiArray internally stores all data in a safe manner for strings and user-defined data structures.

uses
  container.multiarray, utils.functor;

type
  generic TMultiArray<T, BinaryCompareFunctor> = class

BinaryCompareFunctor is based on utils.functor.TBinaryFunctor interface and used to compare two array items in sort and search functions.

TMultiValue

MultiValue uses as internal array item value.

type
  TMultiValue = {$IFDEF FPC}specialize{$ENDIF} TArrayList<T, BinaryCompareFunctor>;

TOptionalMultiValue

If macro {$USE_OPTIONAL} is defined, then all methods return a TOptionalMultiValue wrapper, otherwise TMultiValue.

uses
  utils.optional;

type
  TOptionalMultiValue = {$IFDEF FPC}specialize{$ENDIF} TOptional<TMultiValue>;

For non-existent values, returns a empty TOptionalMultiValue if defined or an EIndexOutOfRangeException is thrown.

type
  {$IFNDEF USE_OPTIONAL}
  EIndexOutOfRangeException = class(Exception);
  {$ENDIF}

Create

A new multi array can be created by call its constructor. It is also possible to reserve memory for items by the first argument.

constructor Create (ALength : Cardinal = 0);
Example
uses
  container.multiarray, utils.functor;

type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;

var
  arr : TIntegerMultiArray;

begin
  arr := TIntegerMultiArray.Create;

  FreeAndNil(arr);
end;

Insert

There are several methods to insert array to the multi array.

Append

Append an array to the end of a TMultiArray. Return true if the request was successful, false if it was not possible to add the new entry.

function Append (ALength : Cardinal = 0) : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  IntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.Append;
  
  FreeAndNil(arr);
end;

Prepend

Prepend an array to the beginning of a TMultiArray. Return true if the request was successful, false if it was not possible to add the new entry.

function Prepend (ALength : Cardinal = 0) : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.Prepend;
  
  FreeAndNil(arr);
end;

Insert

Insert an array at the specified index in a TMultiArray. The index where the new value can be inserted is limited by the size of the array. Returns true if successful, else false (due to an invalid index or if it was impossible to add the more entry).

function Insert (AIndex : LongInt; ALength : Cardinal = 0) : Boolean;
Examples
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.Insert(0);
  
  FreeAndNil(arr);
end;

Remove

The methods to remove array from the multi array.

Remove

Remove the array at the specified location in a TMultiArray. If the array at index doesn't exists, nothing happens and returns false.

function Remove (AIndex: Cardinal) : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.Remove(0);
  
  FreeAndNil(arr);
end;

Remove range

Remove a range of arrays at the specified location in a TMultiArray. If the arrays at indexes don't exists, nothing happens and returns false.

function RemoveRange (AIndex : LongInt; ALength : LongInt) : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.RemoveRange(0, 5);
  
  FreeAndNil(arr);
end;

Clear

Remove all arrays from a TMultiArray.

procedure Clear;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  arr.Clear;
  
  FreeAndNil(arr);
end;

Value

To get value from a TMultiArray use Value property.

property Value [AIndex : LongInt] : {$IFNDEF USE_OPTIONAL}TMultiValue{$ELSE}TOptionalMultiValue{$ENDIF};

If index not exists returns empty TOptionalMultiValue or raise EIndexOutOfRangeException.

Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  
  writeln(arr.Value[0].Value[0]);
  
  FreeAndNil(arr);
end;

Length

Get TMultiArray size.

property Length : LongInt;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  writeln(arr.Length);
  
  FreeAndNil(arr);
end;

IsEmpty

Return true if container is empty.

function IsEmpty : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  
begin
  arr := TIntegerMultiArray.Create;
  if arr.IsEmpty then
    ;
  
  FreeAndNil(arr);
end;

Iterate

It is possible to iterate for TMultiArray arrays using in operator. Each value would present as TMultiArrayList.TIterator object.

uses
  container.multiarray, utils.functor;
  
type
  generic TMultiArray<T, BinaryCompareFunctor> = class
  type
    TIterator = class({$IFDEF FPC}specialize{$ENDIF} TBidirectionalIterator<T, TMultiValue>)
  end;

TBidirectionalIterator is a abstract class which provide interface for iterable object that can moves to both sides.

For ... in ...

Use for ... in ... operator for iterates over container arrays.

Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  val : Integer;
  
begin
  arr := TIntegerMultiArray.Create;
  
  for val in arr do
    ;
  
  FreeAndNil(arr);
end;

FirstEntry

Retrive the iterator for first arrays in a multi array.

function FirstEntry : TIterator;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.FirstEntry;
  
  FreeAndNil(arr);
end;

LastEntry

Retrive the iterator for last array in a multi array.

function LastEntry : TIterator;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.LastEntry;
  
  FreeAndNil(arr);
end;

TIterator

TOptionalIndex

If macro {$USE_OPTIONAL} is defined, then Index method return a TOptionalIndex wrapper, otherwise LongInt.

uses
  utils.optional;

type
  TOptionalIndex = {$IFDEF FPC}specialize{$ENDIF} TOptional<LongInt>;

For non-existent index, returns a empty TOptionalIndex if defined or an EIndexOutOfRangeException is thrown.

type
  {$IFNDEF USE_OPTIONAL}
  EIndexOutOfRangeException = class(Exception);
  {$ENDIF}
HasValue

Return true if iterator has correct value.

function HasValue : Boolean;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.FirstEntry;
  while iterator.HasValue do
  begin
  
    iterator := iterator.Next;
  end;
  
  FreeAndNil(arr);
end;
Prev

Retrieve the iterator for previous array in a multi array.

function Prev : TIterator;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.LastEntry;
  while iterator.HasValue do
  begin
  
    iterator := iterator.Prev;
  end;
  
  FreeAndNil(arr);
end;
Next

Retrieve the iterator for next array in a multi array.

function Next : TIterator;
Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.FirstEntry;
  while iterator.HasValue do
  begin
  
    iterator := iterator.Next;
  end;
  
  FreeAndNil(arr);
end;
Value

To get value use Value property.

property Value : {$IFNDEF USE_OPTIONAL}TMultiValue{$ELSE}TOptionalMultiValue{$ENDIF};

If iterator not have correct value returns empty TOptionalMultiValue or raise EIndexOutOfRangeException.

Example
uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.FirstEntry;
  while iterator.HasValue do
  begin
  	writeln(iterator.Value.Value[0]);
    iterator := iterator.Next;
  end;
  
  FreeAndNil(arr);
end;
Index

Get current array index.

property Index : {$IFNDEF USE_OPTIONAL}LongInt{$ELSE}TOptionalIndex;

If iterator not have correct value returns empty TOptionalIndex or raise EIndexOutOfRangeException.

uses
  container.multiarray, utils.functor;
 
type
  TIntegerMultiArray = {$IFDEF FPC}type specialize{$ENDIF} TMultiArray<Integer, TCompareFunctorInteger>;
 
var
  arr : TIntegerMultiArray;
  iterator : TIntegerMultiArray.TIterator;
  
begin
  arr := TIntegerMultiArray.Create;
  
  iterator := arr.FirstEntry;
  while iterator.HasValue do
  begin
  	writeln(iterator.Index);
    iterator := iterator.Next;
  end;
  
  FreeAndNil(arr);
end;