In the previous blog, we saw what are Arrays in general. Link to that blog Array in general and how to sort 1D array in C Sharp.We also saw how to sort 1-Dimensional Array
In the previous blog we saw,there was nothing fancy. It was just Array's inbuilt sort method doing the trick for us. Now, let's discuss sorting of Jagged and Rectangular Arrays.
Lets sort Jagged Arrays based on "column". I will show you there methods to sort
//a is the array we want to sort by first column.Basically,
// I want output to be like {13,11,19},{27,25,99},{33,12,22}
// & {33,12,21}
int[][] a = new int[][] {
new int[]{13,11,19},
new int[]{33,12,22},
new int[]{33,12,21},
new int[]{27,25,99},
};
SortArray.SortJaggedArray(a,"FIRST");
SortArray is a custom class I wrote. It exposes methods to be called by our Program.cs.Below, you can see how it calls appropriate functions to sort on column,based on columnNumber.
public static int[][] SortJaggedArray(int[][] a,string columnNumber)
{
CustomSortComparerOptions cs = new CustomSortComparerOptions();
if(columnNumber.ToUpper().Equals("FIRST"))
Array.Sort(a, CustomSortComparerOptions.SortByFirstColumn());
if (columnNumber.ToUpper().Equals("SECOND"))
Array.Sort(a, CustomSortComparerOptions.SortBySecondColumn());
if (columnNumber.ToUpper().Equals("FIRST-NON-MATCHING"))
Array.Sort(a, CustomSortComparerOptions.SortByFirstNotEqualColumn());
return a;
}
CustomSortComparerOptions is another class I wrote which has logic to sort the arrays. It has 3 helper classes internally
public static IComparer SortByFirstColumn()
{
return (IComparer)new SortByFirstColumnHelper();
}
private class SortByFirstColumnHelper : IComparer
{
int IComparer.Compare(object? x, object? y)
{
int[] a1 = (int[])x;
int[] a2 = (int[])y;
return (a1[0].CompareTo(a2[0]));
}
}
13 11 19
27 25 99
33 12 22
33 12 21
Here, I have another array which I want to sort by "Second Column"
//a is the array we want to sort by second column
//Output expected is {13,11,19},{33,12,22},{33,12,21},{27,25,99}
int[][] a = new int[][] {
new int[]{27,25,99},
new int[]{33,12,22},
new int[]{13,11,19},
new int[]{33,12,21}
};
SortArray.SortJaggedArray(a);
SortArray class still remain the same except the fact that it now calls my SortBySecondColumn function of CustomSortComparerOptions class.
CustomSortComparerOptions has SortBySecondColumnHelper() and SortBySecondColumn() below
public static IComparer SortBySecondColumn()
{
return (IComparer)new SortBySecondColumnHelper();
}
private class SortBySecondColumnHelper : IComparer
{
int IComparer.Compare(object? x, object? y)
{
int[] a1 = (int[])x;
int[] a2 = (int[])y;
return (a1[1].CompareTo(a2[1]));
}
}
13 11 19
33 12 22
33 12 21
27 25 99
Here, I am using the same array as we saw in our second scenario above
//a is the array we want to sort by first non matching column
//expected output : {13,11,19},{27,25,99},{33,12,21},33,12,22}
int[][] a = new int[][] {
new int[]{27,25,99},
new int[]{33,12,22},
new int[]{13,11,19},
new int[]{33,12,21}
};
SortArray.SortJaggedArray(a);
SortArray still remain the same except the fact that it now calls my SortByFirstNotEqualColumn() function of CustomSortComparerOptions class.
CustomSortComparerOptions - SortByFirstNotEqualColumnHelper() and SortByFirstNotEqualColumn() methods below:
public static IComparer SortByFirstNotEqualColumn()
{
return (IComparer)new SortByFirstNotEqualColumnHelper();
}
private class SortByFirstNotEqualColumnHelper : IComparer
{
int IComparer.Compare(object x, object y)
{
int[] a1 = (int[])x;
int[] a2 = (int[])y;
for (var i = 0; i < a1.Length; i++)
{
for (var j = i; i < a2.Length; j++)
{
if (a1[i] != (a2[j]))
{
return (a1[i].CompareTo(a2[j]));
}
else
{
break;
}
}
}
return -1;
}
}
For eg, array with values {33,12,22} and {33,12,21}, has first 2 columns same i.e 33 and 12, therefore, in this case, column 3 will decide the sorting and therefore, array with third column value 21 is printed before array with third column value 22
13 11 19
27 25 99
33 12 21
33 12 22
Rectangular arrays are also called Multidimensional arrays.These arrrays are uniform arrays.Eg below
int[,] a1 = new int[,] { { 12, 01 }, { 10,13 }, { 19, 27 } ,{ 13, 11 }};
Above is a uniform 2d array.You can't assign a 1d array to a row or column. Point to remember is that, you must index both the row and column, which will eventually get you down to a "single int" in this case.
Unlike Jagged arrays, which is array of arrays,therefore we can reference the first dimension as an array by itself. If you are wondering what it means,then see the code below
//2dArray- Jagged Array
int[][] a = new int[][] {
new int[]{27,25,99},
new int[]{33,12,22},
new int[]{13,11,19},
new int[]{33,12,21}
};
int[] aa = new int[3] {10,12,13};
a[0] = aa;//replaced first element of a
Console.WriteLine(a);// will print [{10,12,13},{33,12,22},{13,11,19},{33,12,21}]
Since you can do above with Jagged arrays, when you call "Array.Sort",you can swap array references as wanted in response to the values returned by the IComparer.Compare method.
a1 array below, declares a rectangular 4-by-2 two-dimensional array, initializing it with numbers {12,01}, {10,13}, { 19, 27 } and { 13, 11 }
Program.cs
int[,] a1 = new int[,] { { 12, 01 }, { 10, 13 }, { 19, 27 }, { 13, 11 } };
Remember how we sorted Jagged Arrays.It was pretty simple to sort Jagged Arrays,however, sorting rectangular arrays are bit more trickier.You cannot "swap rows" in a rectangular array because the entire array in itself is a "one object" rather than an array of one-dimensional arrays.Having said that, you can still sort a rectangular array.To sort a rectangular array, you have to create a second one-dimensional array, which will contain the row numbers of the rectangular array. I created "idTrackingArray" above.The "IComparer.Compare" method will use the passed row numbers to index into the rectangular array and sort the items.
Below is Program.cs
int[,] a1 = new int[,] { { 12, 01 }, { 10, 13 }, { 19, 27 }, { 13, 11 } };
int[] idTrackingArray = new int[] { 0, 1, 2, 3 };
a1 = SortArray.SortMultiDimensionalArray(a1, idTrackingArray,"FIRST");
PrintOutputFor2DRectangularArray(idTrackingArray, a1);
Console.WriteLine("output for sort by FIRST column");
PrintOutputFor2DRectangularArray(idTrackingArray, a1);
Console.WriteLine("-----RESET-----");
a1 = new int[,] { { 12, 01 }, { 10, 13 }, { 19, 27 }, { 13, 11 } };//reset
PrintOutputFor2DRectangularArray(idTrackingArray, a1);
a1 = SortArray.SortMultiDimensionalArray(a1, idTrackingArray, "SECOND");
Console.WriteLine("output for sort by SECOND column");
PrintOutputFor2DRectangularArray(idTrackingArray, a1);
Console.WriteLine("-----RESET----");
SortArray class I wrote, exposes a SortMultiDimensionalArray() function.It basically calls SortByFirstColumn() or SortBySecondColumn() on RectangularComparerOptions instance based on "columnNumber"
public static int[,] SortMultiDimensionalArray(int[,] a,int[] trackerArray, string columnNumber)
{
RectangularComparerOptions rs = new RectangularComparerOptions(a);
if (columnNumber.ToUpper().Equals("FIRST"))
Array.Sort(trackerArray, rs.SortByFirstColumn(a));
if (columnNumber.ToUpper().Equals("SECOND"))
Array.Sort(trackerArray, rs.SortBySecondColumn(a));
return a;
}
Below is the implementation of the RectangularComparerOptions. It has "SortByFirstColumn" and "SortBySecondColumn" methods. Call methods based on what you want to perform.
namespace SortArrayEg
{
public class RectangularComparerOptions
{
// maintain a reference to the 2-dimensional array being sorted
public int[,] sortArray;
// constructor initializes the sortArray reference
public RectangularComparerOptions(int[,] theArray)
{
sortArray = theArray;
}
class SortByFirstColumnHelper : IComparer
{
RectangularComparerOptions r_;
public SortByFirstColumnHelper()
{
}
public SortByFirstColumnHelper(RectangularComparerOptions r1)
{
r_=r1;
}
public int Compare(object x, object y)
{
// x and y are integer row numbers into the sortArray
int i1 = (int)x;
int i2 = (int)y;
// compare the items in the sortArray
return (r_.sortArray[i1, 0].CompareTo(r_.sortArray[i2, 0]));
}
}
class SortBySecondColumnHelper : IComparer
{
RectangularComparerOptions r_;
public SortBySecondColumnHelper()
{
}
public SortBySecondColumnHelper(RectangularComparerOptions r1)
{
r_ = r1;
}
public int Compare(object x, object y)
{
// x and y are integer row numbers into the sortArray
int i1 = (int)x;
int i2 = (int)y;
// compare the items in the sortArray
return (r_.sortArray[i1, 1].CompareTo(r_.sortArray[i2, 1]));
}
}
public IComparer SortByFirstColumn(int[,] a)
{
return (IComparer)new SortByFirstColumnHelper(this);
}
public IComparer SortBySecondColumn(int[,] a)
{
return (IComparer)new SortBySecondColumnHelper(this);
}
}
}
If you call SortByFirstColumn() function the output would be
10 13
12 1
13 11
19 27
If you call SortBySecondColumn() function the output would be
12 1
13 11
10 13
19 27
One thing I would like to mention is that, sometimes it's easier to convert a rectangular array into a Jagged array and then perform the sort. Let's see below how to convert
public static int [][] ConvertMultiDimensionalArrayToJaggedArray(int[,] a)
{
int[][] myJaggedArray = new int[a.GetUpperBound(0) + 1][];
for (int i = 0; i < myJaggedArray.Length; i++)
myJaggedArray[i] = Enumerable.Range(0, a.GetUpperBound(1) + 1).Select(k => a[i, k]).ToArray();
return myJaggedArray;
}
To conclude,I hope you would have got a better understanding on how to Sort Rectangular arrays and Jagged arrays.
Email me at "techspacedeck@gmail.com" incase you have queries. Alternatively, you can fill the "CONTACT" form or drop a comment below