Projet:Scribunto/Guide/Les tables

Introduction modifier

En Lua une table correspond à un tableau ou un hash. On peut y ranger un nombre arbitraire de valeurs, chaque valeur pouvant avoir n'importe quel type (y compris être des tables).
Chaque élément d'une table peut être associé soit à un numéro soit à un texte quelconque (la clé d'accès à la valeur).

Exemples de construction de tables modifier

Quelques exemples :

Table vide modifier

local table = {} -- ceci représente la table vide

Table avec index numérique modifier

-- la table suivante contient 5 éléments de type nombre
local liste = { 1, 5, 3, 7, 2 }

Dans cette table les éléments sont implicitement rangés à partir de l'index 1 dans l'ordre. Ainsi liste[1] vaut 1, liste[2] vaut 5, …, liste[5] vaut 2.
Un élément qui n'existe pas vaut nil.
On peut parcourir les éléments d'un tableau indexé numériquement de la façon suivante :

-- j'ai une table "liste"
local i = 1 -- point de départ
-- tant que liste[i] ne vaut pas 'nil' on traite
while (liste[i] ~= nil) do
  -- je peux traiter liste[i] ici
  -- maintenant je passe à l'élément suivant
  i = i + 1
end

Il est également possible de ranger explicitement des éléments dans une table :

liste[8] = 5
liste[3] = nil
liste[2] = "Hello" -- notez qu'on peut mettre des types différents

Attention : si la table comporte des « trous » la boucle de parcours indiquée plus haut ne fonctionne pas puisqu'elle s'arrête au premier nil trouvé (cette boucle suppose implicitement que les index sont continus jusqu'à la fin de la table).

Table avec index textuel modifier

On peut aussi utiliser des textes au lieu de nombres pour ranger les éléments :

local tab = {}
tab["foo"] = "bar"
tab["bar"] = 5
tab["mon super index"] = 3.14159

Pour initialiser une table avec des index textuels il faut utiliser la syntaxe suivante :

local tab = { ["foo"] = "bar", ["bar"] = 5, ["mon super index"] = 3.14159 }

Ce qui produit exactement le même contenu que dans l'exemple précédent.

Des tables dans des tables modifier

Rien n'empêche de ranger une table dans une table :

local tab = { { 1, 2, 3, 4 }, { {4, 3, 2 }, { "a", "b", "c", "d" } } }

Ceci crée une table tab qui contient :

  • en premier élément (tab[1]) une table contenant la suite 1, 2, 3 et 4 (accessible par tab[1][1], tab[1][2], …)
  • en deuxième élément une table qui contient :
    • en premier élément une table contenant 4, 3, 2
    • en deuxième élément une table contenant "a", "b", "c", "d"

Il est bien sûr possible de combiner des tables de tables et des index textuels. Cela devient toutefois rapidement illisible.
Note : une mise en page appropriée peut aider à mieux comprendre le contenu :

local tab = {
  { 1, 2, 3, 4 },
  {
     {4, 3, 2 },
     { "a", "b", "c", "d" }
  }
}

Parcours des tables modifier

On a vu plus haut un parcours simple d'une table indexée par des nombres.
Il existe des fonctions permettant de parcourir des tables numériques avec trou ou indexées par des textes. Voir à ce propos les fonctions ipairs(), next() et pairs() dans le Reference Manual ainsi que la section sur les manipulations des tables (dans ce même manuel) pour d'autres fonctions s'appliquant aux tables. En particulier :

  • table.concat : utile si on range des éléments (texte ou nombre) dans une table pour ensuite obtenir la concaténation de ces éléments
  • table.sort : pour trier une table
  • table.insert : pour insérer avec décalage dans une table

Attention : les tables ne sont pas copiées modifier

Les tables sont manipulées par référence. Cela veut dire que lorsqu'on passe une table (en paramètre d'une fonction ou pour la copier) on passe en réalité un « pointeur » sur la table d'origine. Ceci signifie que si on modifie l'une ce sera visible dans l'autre − contrairement par exemple à la copie d'un texte qui génère un duplicata.
Exemple :

local tab = {}
tab["x"] = 3
tab["y"] = 5
local tab2 = tab
-- tab2 contient x=3 et y=5, logiquement
tab2["x"] = 99
-- maintenant dans tab2 x=99 ET dans tab x=99

Si vous devez vraiment vous prémunir de ce comportement, par exemple parce que vous passez une table à une fonction qui doit faire des modifications dans la table pour faire son travail, mais que vous désirez garder l'original en l'état, il faut dupliquer la table avant de la passer à la fonction.

La fonction mw.clone(tab) permet de dupliquer la table passée en paramètre. Ceci est valable récursivement, donc même si cette table contient des tables (qui contiennent des tables) le résultat dupliqué sera totalement indépendant. Exemple en reprenant ci-dessus :

local tab = {}
tab["x"] = 3
tab["y"] = 5
local tab2 = mw.clone(tab)
-- tab2 contient x=3 et y=5, logiquement
tab2["x"] = 99
-- maintenant dans tab2 x=99 MAIS dans tab x=3 comme avant
-- puisque les deux tables sont distinctes

Note : mw.clone() est dans le module mw qui est automatiquement présent dans les modules, il n'est donc pas nécessaire de l'inclure explicitement.

Tables de paramètres modifier

Les paramètres reçus lors d'un appel de modèle sont rangés dans une table (table appelée args), mais il s'agit en réalité d'une « méta-table ». Les fonctions pairs() et ipairs() peuvent être utilisées, mais pas d’autres fonctions de table comme next() ou insert(), ni l’opérateur #args qui donne la taille d’une table.