Tableaux

Les tableaux constituent une liste d'éléments indexés.

Il existe 4 types de tableaux :

  • les tableaux statiques, dont la taille est fixe
  • les tableaux dynamiques, dont la taille est variable
  • les tableaux dit "ouverts", destinés au passage de paramètres
  • les tableaux associatifs, dont l'index est d'un type quelconque

Les éléments d'un tableau sont spécifiés et plaçant l'index entre crochets :

table[1] := 10; // place 10 dans l'élément d'indice 1 de 'table'
i := table[2]; // place l'élément d'indice 2 de 'table' dans i

La borne basse des indices peut être récupérée par Low(), la borne haute par High() et le nombre d'élément par Length() (ou Count()).

Pour les tableaux multi-dimensionnels, les indices sont séparés par des virgules ','.

Tableaux statiques

Les tableaux statiques sont des types valeur, une affectation copie les données.

var table : array [1..10] of Integer;

for var i := 1 to 10 do
   table[i] := i;

// strictement équivalent à

for var i := table.Low to table.High do
   table[i] := i;

Un tableau statique dont l'index est un énuméra peut être dimensionné directement avec la syntaxe

type TMyEnum = (alpha, beta, gamma);

// les deux déclarations ci-dessous sont équivalentes
var table1 : array [TMyEnum.Low .. TMyEnum.High] of Integer;
var table2 : array [TMyEnum] of Integer;
var table2 : array [alpha .. gamma] of Integer;  // non-équivalente si TMyEnum est étendu

Tableaux dynamiques

array of type

Les tableaux dynamiques sont un type référence, ils sont déclarés sans étendues, leur borne basse est toujours zéro. Ils peuvent être utilisés comme structure de pile.

var table : array of Integer;
var i : Integer;

table := new Integer[10];
for i:=0 to table.High do
   table[i] := i;

On peut utiliser les opérateurs in et not in pour tester la présence d'un élément.

Ils supportent de plus les pseudo-méthodes suivantes :

  • Add(item) / Push(item) : ajoute un élément à la fin du tableau. Ces méthodes acceptent en paramètre des tableaux dynamiques, et un nombre variable de paramètres, ce qui permet d'ajouter plusieurs éléments avec un seul appel.
  • Clear() : vide le tableau (équivalent à SetLength(0)).
  • Contains(item) : retourne si un élément est contenu, alternative équivalente à in (Qubes 9.0).
  • Copy(startIndex[, count]) : crée un nouveau tableau dynamique contenant count éléments pris depuis startIndex, si count n'est pas spécifié, copie jusqu'à la fin du tableau.
  • Delete(index[, count]) : supprime count élément(s) à l'index spécifié, si count n'est pas spécifié, supprime un seul élément.
  • Filter(filterFunction) : constitue un nouveau tableau comprenant tous les éléments pour lesquels filterFunction a retourné True (Qubes 9.0).
  • ForEach(forEachFunction) : applique une fonction à tous les éléments (Qubes 10.0), cette méthode est plutôt destinée au contexte de transpilation vers JavaScript.
  • IndexOf(item[, startIndex]) : recherche l'index d'un élément, retourne une valeur négative si non trouvé.
  • Insert(index, item) : insère un élément à l'index spécifié.
  • Map(mapFunction) : passe chaque élément du tableau à mapFonction et constitue un nouveau tableau avec les résultats.
  • Move(fromIndex, toIndex) : déplace un élément d'un index vers un autre (Qubes 7.2).
  • Peek() : retourne le dernier élément du tableau.
  • Pop() : retourne le dernier élément et le supprime du tableau.
  • Remove(item[, startIndex]) : supprime la première occurrence de l'élément indiqué s'il existe à partir d'un index et retourne son index, retourne une valeur négative si non trouvé (Qubes 6.1).
  • Reverse() : inverse l'ordre des éléments.
  • SetLength(newLength) : ajuste la longueur du tableau.
  • Sort([compare function]) : effectue un tri du tableau. La fonction de comparaison doit accepter deux éléments et retourner un entier indiquant le résultat de la comparaison. La fonction de comparaison est optionnelle pour les tableaux d'entier, de flottants et de chaîne (tri non sensible à la casse par défaut).
  • Swap(index1, index2) : échange les éléments d'index spécifiés.

array of String

Les tableaux de chaînes possèdent les pseudo-méthodes complémentaires suivantes :

  • Join(delimiter) : renvoie une chaîne constituée par toutes les chaînes du tableau séparées par le délimiteur indiqué.
// exemple de tri avec fonction de comparaison et jointure pour affichage du résultat

function CompareAfterSpace(a, b : String) : Integer;
begin
   Result := a.After(' ').CompareText(b.After(' '));
end;

var s : array of String;

s.Add('hello world', 'bye bye');
s.Sort(CompareAfterSpace);
PrintLn(s.Join(','));

array of Float

Les tableaux de flottants à partir de Qubes 9.0 possèdent les pseudo-méthodes complémentaires suivantes :

  • Multiply(facteur) : multiplie tous les éléments du tableau par le facteur et renvoi le tableau.
  • MultiplyAdd(facteur, offset) : multiplie tous les éléments du tableau par le facteur, ajoute l'offset, puis renvoi le tableau (Qubes 10.0).
  • Offset(delta) : ajoute delta à tous les éléments du tableau et renvoi le tableau.
  • Reciprocal : applique la réciproque (1/x) à tous les éléments du tableau et renvoi le tableau.

Tableaux ouverts

Ils sont à déclarer en tant que paramètres comme 'array of const'.

Limites

Les tableaux statiques résident sur la pile, au sein d'un record ou d'une classe, leur taille limite sera de l'ordre de quelques dizaine à quelques centaines de milliers d'éléments. En pratique il est préférable de les réserver à de petits tableaux pour des considérations de performance.

Les tableaux dynamiques sont alloués dynamiquement, et limités par la mémoire disponible.
A compter de la 9.2021.0308 ils supportent plus de 2147483648 éléments, limite dépassable uniquement dans un contexte 64bits, un tableau de cette taille occupera par exemple:

  • éléments Float ou Integer, 8 octets / élément, soit 16 Go de mémoire
  • éléments Boolean, 1 bit / élément, soit 256 Mo de mémoire

Préalablement à la 9.2021.0308, l'encombrement par élément est 16 octets en 32 bits, et 24 octets en 64 bits.