65.9K
CodeProject is changing. Read more.
Home

Sorting a Two-Dimensional Array in C#

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (11 votes)

Mar 8, 2011

CPOL
viewsIcon

80864

How to sort a two-dimensional array in C#

I'm a fan of Linq and extension methods for things like this. So, how does this look to you?

public static class MultiDimensionalArrayExtensions
{
  /// <summary>
  ///   Orders the two dimensional array by the provided key in the key selector.
  /// </summary>
  /// <typeparam name="T">The type of the source two-dimensional array.</typeparam>
  /// <param name="source">The source two-dimensional array.</param>
  /// <param name="keySelector">The selector to retrieve the column to sort on.</param>
  /// <returns>A new two dimensional array sorted on the key.</returns>
  public static T[,] OrderBy<T>(this T[,] source, Func<T[], T> keySelector)
  {
      return source.ConvertToSingleDimension().OrderBy(keySelector).ConvertToMultiDimensional();
  }
  /// <summary>
  ///   Orders the two dimensional array by the provided key in the key selector in descending order.
  /// </summary>
  /// <typeparam name="T">The type of the source two-dimensional array.</typeparam>
  /// <param name="source">The source two-dimensional array.</param>
  /// <param name="keySelector">The selector to retrieve the column to sort on.</param>
  /// <returns>A new two dimensional array sorted on the key.</returns>
  public static T[,] OrderByDescending<T>(this T[,] source, Func<T[], T> keySelector)
  {
      return source.ConvertToSingleDimension().
      	OrderByDescending(keySelector).ConvertToMultiDimensional();
  }
  /// <summary>
  ///   Converts a two dimensional array to single dimensional array.
  /// </summary>
  /// <typeparam name="T">The type of the two dimensional array.</typeparam>
  /// <param name="source">The source two dimensional array.</param>
  /// <returns>The repackaged two dimensional array as a single dimension based on rows.</returns>
  private static IEnumerable<T[]> ConvertToSingleDimension<T>(this T[,] source)
  {
      T[] arRow;
 
      for (int row = 0; row < source.GetLength(0); ++row)
      {
          arRow = new T[source.GetLength(1)];
 
          for (int col = 0; col < source.GetLength(1); ++col)
              arRow[col] = source[row, col];
 
          yield return arRow;
      }
  }
  /// <summary>
  ///   Converts a collection of rows from a two dimensional array back into a two dimensional array.
  /// </summary>
  /// <typeparam name="T">The type of the two dimensional array.</typeparam>
  /// <param name="source">The source collection of rows to convert.</param>
  /// <returns>The two dimensional array.</returns>
  private static T[,] ConvertToMultiDimensional<T>(this IEnumerable<T[]> source)
  {
      T[,] twoDimensional;
      T[][] arrayOfArray;
      int numberofColumns;
 
      arrayOfArray = source.ToArray();
      numberofColumns = (arrayOfArray.Length > 0) ? arrayOfArray[0].Length : 0;
      twoDimensional = new T[arrayOfArray.Length, numberofColumns];
 
      for (int row = 0; row < arrayOfArray.GetLength(0); ++row)
          for (int col = 0; col < numberofColumns; ++col)
              twoDimensional[row, col] = arrayOfArray[row][col];
 
      return twoDimensional;
  }
}

Then, to be able to use the code above, you would simply do something like the following:

int[,] array = new int[3, 3] { { 1, 4, 2 }, { 4, 5, 1 }, { 7, 3, 8 } };
 
int[,] sortedByFirstElement = array.OrderBy(x => x[0]);
int[,] sortedBySecondElement = array.OrderBy(x => x[1]);
int[,] sortedByThirdElement = array.OrderBy(x => x[2]);

The keyselector Func is merely the way to determine the column to sort on using lambdas.