How To Sort Two Dimensional Array By Selected Column Index In Selected Column Sort Order

Introduction

 
Almost every program I have created needs a method for sorting a two-dimensional array by column one in the selected sort order, then by column two in the selected sort order, and then by column three in selected sort order ... then by column n in the selected sort order.
 
For sorting two-dimensional arrays containing different types of values, integers, strings, booleans, etc., I have used DataGridView class and its DataGridViewSort event handler. It is easy to manipulate with data in any way and offers fast sorting as well. An article about that can be found here.
 
But sometimes, it is not possible to implement such a solution. So, I have made the decision to try to write my own universal method for sorting 2D arrays, that could be used for sorting arrays in any future program that I am going to write.
 
After a while, I have written this method.
  1. /// <summary>      
  2. /// Sorts two dimensional array type of string,      
  3. /// by selected culumns, in selected sort order.      
  4. /// Selection Sort Algorithm is implemented      
  5. /// for sorting values inside array.      
  6. /// </summary>      
  7. /// <param name="array">      
  8. /// Two dimensional array, type of string,      
  9. /// contaning values that are going to be sorted.      
  10. /// </param>      
  11. /// <param name="sort_directive">      
  12. /// Two dimensional array, type of int.      
  13. /// First column contains the order of the column indexes      
  14. /// by which the array will be sorted.      
  15. /// Second column contains column sort order.      
  16. /// Sort order for each column is defined by ineger values :      
  17. /// -1 - sort column values in Descending sort order      
  18. ///  0 - column is not going to be sorted      
  19. ///  1 - sort column values in Ascending sort order      
  20. /// </param>      
  21. /// <returns>      
  22. /// Sorted array by selected columns in selected sort order.      
  23. /// </returns>      
  24. public string[,] Sort_String(string [,] array, int [,] sort_directive)      
  25. {      
  26.     // number of rows iside array      
  27.     int array_rows = array.GetLength(0);      
  28.     // number of columns inside array      
  29.     int array_columns = array.Length/array_rows;      
  30.     // number of columns to be sorted      
  31.     int sort_directive_columns = sort_directive.GetLength(0);      
  32.     //      
  33.     for(int i=0;i<array_rows-1;i++)      
  34.     {      
  35.         for(int j=i+1;j<array_rows;j++)      
  36.         {      
  37.             for(int c=0;c<sort_directive_columns;c++)      
  38.             {      
  39.                 //      
  40.                 // sort array values in descending sort order      
  41.                 //      
  42.                 if(sort_directive[c,1]==-1 &&      
  43.                    array[i,sort_directive[c,0]].CompareTo(array[j,sort_directive[c,0]])<0)      
  44.                 {      
  45.                     //      
  46.                     // if values are in ascending sort order      
  47.                     // swap values      
  48.                     //      
  49.                     for(int d=0;d<array_columns;d++)      
  50.                     {      
  51.                         string h = array[j,d];      
  52.                         array[j,d]=array[i,d];      
  53.                         array[i,d]=h;      
  54.                     }      
  55.                           
  56.                     break;      
  57.                 }      
  58.                 //      
  59.                 // if values are in correct sort order break      
  60.                 //      
  61.                 else if(sort_directive[c,1]==-1 &&      
  62.                         array[i,sort_directive[c,0]].CompareTo(array[j,sort_directive[c,0]])>0)      
  63.                     break;      
  64.                 //      
  65.                 // sort array values in ascending sort order      
  66.                 //      
  67.                 else if(sort_directive[c,1]==1 &&      
  68.                         array[i,sort_directive[c,0]].CompareTo(array[j,sort_directive[c,0]])>0)      
  69.                 {      
  70.                     //      
  71.                     // if values are in descending sort order      
  72.                     // swap values      
  73.                     //      
  74.                     for(int d=0;d<array_columns;d++)      
  75.                     {      
  76.                         string h = array[j,d];      
  77.                         array[j,d]=array[i,d];      
  78.                         array[i,d]=h;      
  79.                     }      
  80.                           
  81.                     break;      
  82.                 }      
  83.                 //      
  84.                 // if values are in correct sort order break      
  85.                 //      
  86.                 else if(sort_directive[c,1]==1 &&      
  87.                         array[i,sort_directive[c,0]].CompareTo(array[j,sort_directive[c,0]])<0)      
  88.                     break;      
  89.                 //      
  90.                 // if values are equal      
  91.                 // select next sort directive     
  92.                 //      
  93.             }      
  94.         }      
  95.     }      
  96.           
  97.     return array;      
  98. }      

How did I develop this method?

 
First, the decision was that the 2D array should strictly be the type of string. Since any other type of data (int, double, float, decimal, char, boolean, ...) can be represented as a string value, and because of that, the 2D array type of string could contain diverse types of data that could be easily manipulated and sorted.
 
Important
 
Data stored inside the array type of string are always represented (memorized) as a type of String. When sorting, all data are compared as strings, and numbers also. If there is a need to sort numbers, it is necessary to adjust the format of data, so that the sort routine returns the correct result.
 
 numerical data
as strings
 numerical data
formated for sorting as number values
sorted correctly
as numbers
 "1"   "0001"   "0001"
 "10"  "0010"  "0003"
 "214"  "0214"  "0004"
 "3"  "0003"   "0005"
 "4"  "0004"  "0010"
 "5"  "0005"  "0214"
 "1024"  "1024"  "1024"

numerical data
as strings
numerical data
not formated for sorting as number values
sorted correctly
as strings
    "1"  "1"  "1"
  "10"  "10"  "10"
"214"  "214"  "1024"
    "3"  "3"  "214"
   "4"  "4"  "3"
    "5"  "5"  "4"
"1024"  "1024"  "5"

Example of formatting numerical data.
  1. int numerical_data = 100;      
  2. string format = "000000";      
  3. string formated_data = numerical_data.ToString(format);      
Result of formatting.

Numerical data  Formatted data

         100                000100

The name of the 2D array inside the program shall be TABLE.

Declaration of TABLE with 10 rows and 10 columns, max 100 elements.
  1. int rows = 10;      
  2. int columns = 10;      
  3.       
  4. string [,] TABLE = new string[rows,columns];      
The second decision was to use a 2D array type of integer for storing TABLE sort directives.

A simple sort directive looks like this.

Sort TABLE by Column One in Ascending sort order.

As shown, sort directive consists of selected TABLE column index and its sort order.

So this array should have only two columns. 

The first column shall contain a selected column index.

The second column contains column sort order defined by integer values.
  • - 1 - sort column values in Descending sort order
  •   0 - column is not going to be sorted
  •   1 - sort column values in Ascending sort order
The number of rows depends on how many sort directives are entered by the user.

Name of the 2D array inside program shall be SORT_DIRECTIVE.

Declaration of SORT_DIRECTIVE,
  1. int rows = number of sort directives;      
  2. int columns = 2;      
  3.       
  4. string [,] SORT_DIRECTIVE = new string[rows,columns];       

Example of sort directive and SORT_DIRECTIVE element values


TABLE has seven rows and three columns,
  • Sort TABLE by Column One in Ascending sort order then by
  • Column Two in Descending sort order then by
  • Column Three in Ascending sort order.
         SORT_DIRECTIVE
                  1           1
                  2          -1
                  3           1

The third and final decision was the selection of Sort Algorithm.

I have decided to use the Selection Sort Algorithm for its simplicity of implementation. Also, it is fast enough for a small amount of data, up to 1000 records.
 

How does it work?


Create and fill TABLE with data. Be careful if some column should contain numbers. Numbers must be specially formatted for sorting as described in the important notice above. 
  1. //    
  2. // Create and fill TABLE    
  3. //    
  4. string [,] TABLE = new string[7,3]    
  5. {    
  6.     { "John"     , "Porter"    , "1234 Oak street, Pensacola, FL 32503"         },    
  7.     { "John"     , "Porter"    , "1891 3rd Street North Westlake, OH 44145"     },    
  8.     { "William"  , "Patterson" , "4534 Virginia Street Dallas, GA 30132"        },    
  9.     { "Marry"    , "Cortez"    , "7642 Fairview Avenue Milwaukee, WI 53204"     },    
  10.     { "John"     , "Patterson" , "1368 Street Road Morristown, NJ 07960"        },    
  11.     { "Elizabet" , "Cortez"    , "3698 Cedar Avenue Saratoga Springs, NY 12886" },    
  12.     { "Marry"    , "Mosley"    , "4575 11th Street Sacramento, CA 95820"        }    
  13.         
  14. };   
Then, create and fill SORT_DIRECTIVE.
  1. //    
  2. // Table SORT DIRECTIVE contains order of columns    
  3. // by which array is going to be sorted and sort order    
  4. // for each selected column    
  5. //    
  6. //  0 - do not sort column    
  7. // -1 - sort in Descending order    
  8. //  1 - sort in Ascending order    
  9. //    
  10. int [,] SORT_DIRECTIVE=new int[3,2]    
  11. {    
  12.     {0,  1},    
  13.     {1, -1},    
  14.     {2,  1}    
  15. };    
Call method.
  1. //  
  2. // Call sort method  
  3. //  
  4. TABLE = Sort_String(TABLE,SORT_DIRECTIVE); 
When finished, method returns sorted array TABLE by values inside SORT_DIRECTIVE.
  1. //    
  2. // Print sorted TABLE    
  3. //    
  4. Console.WriteLine();    
  5. Console.WriteLine("  SORTED TABLE");    
  6. Console.WriteLine(" --------------");    
  7. Console.WriteLine();    
  8. for(int n=0;n<7;n++)    
  9. {    
  10.     Console.WriteLine("  {0,-10}{1,-10}{2,-10}",TABLE[n,0],TABLE[n,1],TABLE[n,2]);    
  11. }    
  12. Console.WriteLine(" --------------");    
  13. //    
  14. //    
  15. //    
Here is the program's screenshot.
 
How To Sort Two Dimensional Array By Selected Column Index In Selected Column Sort Order
 
Notice
Names and addresses shown in the picture are fictional.
 

Conclusion

 
For sorting up to a thousand rows filled with data, this method is almost as fast as DataGridView with its SortEventHandler. If there is a need for sorting more data than that, perhaps by implementing faster sort algorithm, things would be better. This method can easily be changed to sort 2D arrays of any type, inside open source solution there is class Sort_2D_Array containing these methods,
  • Sort_String
  • Sort_Int
  • Sort_Double
  • Sort_Decimal
  • Sort_Float 
Name of the method shows what is the type of array that is going to be sorted.
 
Download link for open source solution is at the beginning of this article. The archive is called TAS.zip ( two-dimensional array sort ). The solution was created in IDE SharpDevelop and needs .NET 4.0 to work correctly.