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
}
}