CodeGym /Cours /C# SELF /Tableaux dentelés (Jagged Arrays) en C#

Tableaux dentelés (Jagged Arrays) en C#

C# SELF
Niveau 7 , Leçon 5
Disponible

1. Quelle est la différence entre les tableaux dentelés et les tableaux à deux dimensions

Voilà, on arrive à un sujet que beaucoup appellent «tableaux de tableaux» ou «tableaux dentelés» — en anglais jagged arrays. Contrairement aux tableaux à deux dimensions, les tableaux dentelés te permettent de stocker des colonnes de longueurs différentes. C'est comme si tu avais un complexe d'immeubles, où chaque immeuble a son propre nombre d'appartements — dans un immeuble il y en a 5, dans un autre 20, et dans le troisième — juste un seul.

Un tableau dentelé, c'est un tableau dont chaque élément est lui-même un tableau. Et les tableaux internes (on les appelle aussi «sous-tableaux») peuvent avoir des longueurs différentes.

La différence principale :

  • Dans un tableau à deux dimensions, chaque «ligne» (et chaque «colonne») a le même nombre d'éléments. Exemple : int[,] grid = new int[3, 5]; — on a toujours 3 lignes de 5 éléments.
  • Dans un tableau dentelé, chaque ligne peut avoir une longueur différente ! Exemple : int[][] jagged = new int[3][]; — et ensuite on initialise chaque ligne (sous-tableau) comme on veut.

Voilà à quoi ça ressemble visuellement :

Tableau à deux dimensions Tableau dentelé
Nombre d'éléments Strictement fixe (par exemple, 3x5) Peut varier selon les lignes
Indexation
[i, j]
[i][j]
Flexibilité Basse Haute
Utilisation Tableaux, maths Données irrégulières :
listes d'étudiants avec un nombre différent de notes, triangles

Visualisation : comparons un tableau à deux dimensions et un tableau dentelé

Tableau à deux dimensions (3x3) :
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┴───┴───┘

Tableau dentelé (longueurs différentes) :
┌───┬───┐
│ 1 │ 2 │
├───┼───┼───┬───┐
│ 3 │ 4 │ 5 │ 6 │
├───┼───┴───┴───┘
│ 7 │
└───┘

2. Syntaxe de déclaration et d'initialisation d'un tableau dentelé

Déclarer un tableau dentelé, c'est pas plus flippant que de déclarer les autres types ! Faut pas avoir peur des doubles crochets :

int[][] jaggedArray = new int[3][];
Déclaration d'un tableau dentelé

Ça veut dire qu'on a un tableau de 3 éléments, et chacun d'eux est aussi un tableau d'int. Mais pour l'instant, les tableaux internes ne sont pas encore créés ! Pour mieux piger, on va détailler ça.

Initialisation étape par étape d'un tableau dentelé

Étape 1 — création du tableau principal (externe) :

int[][] jaggedArray = new int[3][];

Maintenant on a 3 «lignes», mais elles valent toutes null pour l'instant.

Étape 2 — création et remplissage des tableaux internes (sous-tableaux) :

Par exemple, la première ligne fera 2, la deuxième — 4, la troisième — 3 :

jaggedArray[0] = new int[2]; // 2 éléments dans la première ligne
jaggedArray[1] = new int[4]; // 4 éléments dans la deuxième ligne
jaggedArray[2] = new int[3]; // 3 éléments dans la troisième ligne

Étape 3 — remplissage avec des valeurs :

Les tableaux internes sont des tableaux normaux ! Par exemple :

jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;

jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
jaggedArray[1][3] = 6;

jaggedArray[2][0] = 7;
jaggedArray[2][1] = 8;
jaggedArray[2][2] = 9;

Initialisation rapide d'un tableau dentelé

Tu peux créer et remplir un tableau dentelé d'un coup si tu connais déjà les valeurs :

int[][] jaggedArray = new int[][]
{
    new int[] { 1, 2 },
    new int[] { 3, 4, 5, 6 },
    new int[] { 7, 8, 9 }
};

Ou encore plus court, sans préciser le type des tableaux internes :

int[][] jaggedArray = {
    new[] { 1, 2 },
    new[] { 3, 4, 5, 6 },
    new[] { 7, 8, 9 }
};

3. Parcourir et bosser avec des tableaux dentelés

Parcourir un tableau dentelé, c'est pas plus compliqué qu'un tableau à deux dimensions, mais maintenant la boucle externe va sur les lignes, et la boucle interne sur les éléments de la ligne (qui peuvent avoir des longueurs différentes) :

for (int i = 0; i < jaggedArray.Length; i++)
{
    Console.WriteLine($"Ligne {i}:");
    for (int j = 0; j < jaggedArray[i].Length; j++)
    {
        Console.Write($"{jaggedArray[i][j]} ");
    }
    Console.WriteLine();
}

Résultat à l'écran :

Ligne 0:
1 2 
Ligne 1:
3 4 5 6 
Ligne 2:
7 8 9 

Tu peux utiliser foreach pour pas te prendre la tête avec les index :

foreach (int[] row in jaggedArray)
{
    foreach (int value in row)
    {
        Console.Write($"{value} ");
    }
    Console.WriteLine();
}

4. Organisation interne d'un tableau de tableaux

Et maintenant tu vas voir comment sont vraiment organisés les tableaux de tableaux. Prêt ?

Si avec un tableau normal «la variable-tableau stocke une référence vers un conteneur qui stocke les éléments du tableau». Avec les tableaux dentelés, c'est un peu plus explosif : la variable-tableau-de-tableaux stocke une référence vers un conteneur qui stocke des références vers des tableaux à une dimension. C'est plus simple à voir qu'à expliquer cent fois :

How two-dimensional arrays work

À gauche on a «la variable-tableau-de-tableaux» qui stocke une référence vers «l'objet-conteneur de tableaux». Au milieu on a «l'objet-conteneur de tableaux», dans les cases duquel on trouve des références vers des tableaux à une dimension — les lignes du tableau dentelé. Et à droite tu vois quatre tableaux à une dimension — les lignes de notre tableau dentelé.

Voilà comment sont vraiment faits les tableaux dentelés. Et cette approche donne plusieurs avantages au programmeur C# :

Premièrement, comme le «conteneur de conteneurs» stocke des références vers les «tableaux-lignes», on peut très vite et facilement échanger les lignes. Pour accéder au «conteneur de conteneurs», il suffit de donner un seul index au lieu de deux. Exemple :
int[][] data = new int[2][];
data[0] = new int[5]; // première ligne — tableau de 5 éléments
data[1] = new int[5]; // deuxième ligne — tableau de 5 éléments

int[] row1 = data[0];
int[] row2 = data[1];

Avec ce genre de code, tu peux échanger les lignes :

// Matrice importante avec des données
int[][] matrix = {
  new int[] {1, 2, 3, 4, 5},
  new int[] {5, 4, 3, 2, 1}
};

int[] tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;

Si tu accèdes à une case d'un tableau à deux dimensions mais qu'après le nom du tableau tu mets juste un index, tu accèdes alors au conteneur de conteneurs, dans lequel il y a des références vers des tableaux à une dimension.

5. Scénarios typiques d'utilisation des tableaux dentelés

Quand un tableau dentelé peut-il être plus utile qu'un tableau à deux dimensions ?

  • Si tu stockes pour chaque utilisateur un nombre différent de données : notes par matière, achats, commentaires, etc.
  • Si tes données ont une structure triangulaire ou en escalier (genre pour afficher des pyramides, triangles de Pascal, etc.).
  • Si tu veux économiser de la mémoire : dans un tableau à deux dimensions toutes les lignes sont fixes, alors que dans un tableau dentelé — juste le nombre d'éléments nécessaire.

Exemple de la vraie vie : gestionnaire de notes d'étudiants

On va améliorer notre projet d'apprentissage ! Imaginons que chaque étudiant peut avoir un nombre différent de notes pour chaque matière. Genre, certains rendent plus de devoirs, d'autres moins. Pour ça, le tableau dentelé est parfait.

Imaginons qu'on a trois étudiants, et voilà leurs notes pour différents devoirs de maths :

Étudiant Notes
0 5, 4
1 3, 4, 4
2 5

On déclare ce tableau :

int[][] studentMarks = new int[3][];
studentMarks[0] = new int[] { 5, 4 };         // Premier étudiant - 2 notes
studentMarks[1] = new int[] { 3, 4, 4 };      // Deuxième étudiant - 3 notes
studentMarks[2] = new int[] { 5 };            // Troisième étudiant - 1 note

On affiche les notes de chaque étudiant :

for (int i = 0; i < studentMarks.Length; i++)
{
    Console.Write($"Étudiant {i}: ");
    for (int j = 0; j < studentMarks[i].Length; j++)
    {
        Console.Write(studentMarks[i][j] + " ");
    }
    Console.WriteLine();
}

Utiliser des tableaux dentelés avec d'autres types

Un tableau dentelé peut contenir n'importe quoi : des chaînes, des tableaux de tableaux (encore plus profond !), même tes propres objets.

Exemple : tableau de chaînes

string[][] groups = new string[][]
{
    new string[] { "Ivan", "Piotr" },
    new string[] { "Maria", "Alexei", "Sergei" },
    new string[] { "Vasilisa" }
};

6. Particularités et erreurs possibles

Les tableaux dentelés, c'est super flexible, mais y a des pièges partout.

  • Si tu n'as pas initialisé un des tableaux internes (jaggedArray[1] = ...), essayer d'y accéder va te donner une NullReferenceException. N'oublie pas d'initialiser chaque tableau interne !
  • Toutes les lignes (sous-tableaux) n'ont pas la même longueur. Si tu utilises un index fixe dans la deuxième dimension, tu peux sortir des limites.
  • Ne confonds pas avec un tableau à deux dimensions ! L'indexation c'est : array[i][j], et pas array[i, j].
1
Étude/Quiz
Tableaux, niveau 7, leçon 5
Indisponible
Tableaux
Découverte des tableaux
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION