using System; using System.Collections.Generic; using System.Linq; namespace Developpez.Dotnet.Collections { /// /// Fournit des méthodes d'extension pour la manipulation de tableaux /// public static class ArrayExtensions { #region Jagged and multidimensional arrays /// /// Renvoie une séquence contenant les lignes d'un tableau bidimensionnel. /// /// Type des éléments du tableau /// Tableau bidimensionnel dont on veut obtenir les lignes. /// Une séquence contenant les lignes du tableau public static IEnumerable GetRows(this T[,] array) { array.CheckArgumentNull("array"); return array.GetRowsImpl(); } private static IEnumerable GetRowsImpl(this T[,] array) { int rows = array.GetLength(0); int columns = array.GetLength(1); for (int i = 0; i < rows; i++) { T[] row = new T[columns]; for (int j = 0; j < columns; j++) { row[j] = array[i, j]; } yield return row; } } /// /// Renvoie un tableau en escalier avec le même contenu que le tableau bidimensionnel spécifié. /// /// Type des éléments du tableau /// Tableau bidimensionnel à convertir /// Un tableau en escalier avec le même contenu que le tableau bidimensionnel spécifié. public static T[][] ToJaggedArray(this T[,] array) { return array.GetRows().ToArray(); } /// /// Renvoie un tableau bidimensionnel avec le même contenu que le tableau en escalier spécifié. /// /// Type des éléments du tableau /// Tableau en escalier à convertir. /// Un tableau bidimensionnel avec le même contenu que le tableau en escalier spécifié. /// Le nombre de colonnes est déterminé en recherchant la plus longue ligne du tableau en escalier. /// Pour de meilleures performances, si vous savez que toutes les lignes ont la même longueur, utilisez la /// surcharge prenant un paramètre bool useFirstLineLength. public static T[,] ToBidimensionalArray(this T[][] jaggedArray) { return jaggedArray.ToBidimensionalArray(false); } /// /// Renvoie un tableau bidimensionnel avec le même contenu que le tableau en escalier spécifié. /// /// Type des éléments du tableau /// Tableau en escalier à convertir. /// true pour utiliser la longueur de la première ligne comme nombre de colonnes, false pour rechercher la ligne la plus longue. /// Un tableau bidimensionnel avec le même contenu que le tableau en escalier spécifié. /// Si useFirstLineLength vaut false, le nombre de colonnes est déterminé en recherchant la plus longue ligne /// du tableau en escalier. Pour de meilleures performances, si vous savez que toutes les lignes ont la même longueur, passez true /// pour le paramètre useFirstLineLength (une exception sera alors levée si une ligne est plus longue que la première). public static T[,] ToBidimensionalArray(this T[][] jaggedArray, bool useFirstLineLength) { jaggedArray.CheckArgumentNull("jaggedArray"); int rows = jaggedArray.Length; int columns = 0; if (useFirstLineLength && jaggedArray.Length != 0) columns = jaggedArray[0].Length; else columns = jaggedArray.Select(row => row.Length).DefaultIfEmpty().Max(); T[,] array = new T[rows, columns]; for (int i = 0; i < rows; i++) { T[] row = jaggedArray[i]; int cols = row.Length; for (int j = 0; j < row.Length; j++) { array[i, j] = row[j]; } } return array; } #endregion #region ArraySegment related methods /// /// Renvoie le segment demandé d'un tableau /// /// Type des éléments du tableau /// Tableau dont on veut obtenir un segment /// Index de début du segment /// Nombre d'éléments dans le segment /// Le segment demandé du tableau public static ArraySegment GetSegment(this T[] array, int from, int count) { return new ArraySegment(array, from, count); } /// /// Renvoie un segment d'un tableau à partir de la position spécifiée /// /// Type des éléments du tableau /// Tableau dont on veut obtenir un segment /// Index de début du segment /// Le segment de tableau qui commence à la position spécifiée public static ArraySegment GetSegment(this T[] array, int from) { return GetSegment(array, from, array.Length - from); } /// /// Renvoie un segment de tableau représentant la totalité du tableau /// /// Type des éléments du tableau /// Tableau dont on veut obtenir un segment /// Un segment représentant la totalité du tableau public static ArraySegment GetSegment(this T[] array) { return new ArraySegment(array); } /// /// Renvoie une séquence qui énumère les éléments d'un segment de tableau /// /// Type des éléments du tableau /// Segment de tableau à énumérer /// Une séquence correspondant aux éléments du segment de tableau public static IEnumerable AsEnumerable(this ArraySegment arraySegment) { return arraySegment.Array.Skip(arraySegment.Offset).Take(arraySegment.Count); } /// /// Renvoie un nouveau tableau à partir d'un segment de tableau /// /// Type des éléments du tableau /// Segment de tableau à partir duquel est créé le nouveau tableau /// Un tableau contenant tous les éléments du segment d'origine public static T[] ToArray(this ArraySegment arraySegment) { T[] array = new T[arraySegment.Count]; Array.Copy(arraySegment.Array, arraySegment.Offset, array, 0, arraySegment.Count); return array; } #endregion #region ShiftLeft, ShiftRight /// /// Décale les éléments d'un tableau d'une position vers la gauche, /// en remplaçant le dernier élément par la valeur par défaut du type /// des éléments du tableau. Cette méthode ne modifie pas le tableau d'origine /// mais renvoie un nouveau tableau. /// /// Type des éléments du tableau /// Tableau à décaler /// Une copie décalée du tableau d'origine public static T[] ShiftLeft(this T[] array) { return array.ShiftLeft(default(T)); } /// /// Décale les éléments d'un tableau d'une position vers la gauche, /// en remplaçant le dernier élément par la valeur spécifiée. /// Cette méthode ne modifie pas le tableau d'origine mais renvoie un /// nouveau tableau. /// /// Type des éléments du tableau /// Tableau à décaler /// Valeur à insérer à la fin du tableau /// Une copie décalée du tableau d'origine public static T[] ShiftLeft(this T[] array, T value) { T[] newArray = new T[array.Length]; Array.Copy(array, 1, newArray, 0, array.Length - 1); newArray[array.Length - 1] = value; return newArray; } /// /// Décale les éléments d'un tableau d'une position vers la droite, /// en remplaçant le premier élément par la valeur par défaut du type /// des éléments du tableau. Cette méthode ne modifie pas le tableau d'origine /// mais renvoie un nouveau tableau. /// /// Type des éléments du tableau /// Tableau à décaler /// Une copie décalée du tableau d'origine public static T[] ShiftRight(this T[] array) { return array.ShiftRight(default(T)); } /// /// Décale les éléments d'un tableau d'une position vers la droite, /// en remplaçant le premier élément par la valeur spécifiée. /// Cette méthode ne modifie pas le tableau d'origine mais renvoie un /// nouveau tableau. /// /// Type des éléments du tableau /// Tableau à décaler /// Valeur à insérer au début du tableau /// Une copie décalée du tableau d'origine public static T[] ShiftRight(this T[] array, T value) { T[] newArray = new T[array.Length]; Array.Copy(array, 0, newArray, 1, array.Length - 1); newArray[0] = value; return newArray; } #endregion #region RotateLeft, RotateRight /// /// Effectue une rotation d'un tableau d'une position vers la gauche. /// Cette méthode ne modifie pas le tableau d'origine mais renvoie un /// nouveau tableau. /// /// Type des éléments du tableau /// Tableau sur lequel effectuer une rotation /// Une copie du tableau d'origine sur laquelle une rotation a été effectuée public static T[] RotateLeft(this T[] array) { return array.ShiftLeft(array.First()); } /// /// Effectue une rotation d'un tableau d'une position vers la droite. /// Cette méthode ne modifie pas le tableau d'origine mais renvoie un /// nouveau tableau. /// /// Type des éléments du tableau /// Tableau sur lequel effectuer une rotation /// Une copie du tableau d'origine sur laquelle une rotation a été effectuée public static T[] RotateRight(this T[] array) { return array.ShiftRight(array.Last()); } #endregion } }