#Computing is Fun : Working with Sorting in C#

Siapa sih gak pernah buat sorting ? baik para scientist maupun business dev sering melakukan sorting terhadap data seperti dalam database ataupun saat menampilkan data di DataGrid ataupun GridView untuk aplikasi .NET. Di session Computing is Fun kali ini akan membuat mengenai sorting. Disini akan dijabarkan bagaimana membuat object sorting yang dapat digunakan untuk semua kebutuhan (general requirements) dengan implementasi dalam C#. Sebelum membahas sorting, disini diasumsikan bahwa kita membuat data collection berupa object Employee dan collection ini akan dilakukan sorting berdasarkan propertie yang dimiliki. Untuk lebih mudahnya object Employee dapat digambarkan sebagai berikut


Supaya lebih fokus pembahasan dalam sorting dari sebuah collection, saya membagi 2 topik sorting yaitu

  • Sorting pada Non Generics Collection
  • Sorting pada Generics Collection

Masing-masing topik ini akan dibahas sub item selanjutnya.

Sorting pada Non Generics Collection
Non Generics Collection yang akan digunakan disini adalah ArrayList yang merupakan bagian dari namespace System.Collection. Pada object ArrayList telah menyediakan method Sort yang berguna untuk sorting. Agar method Sort ini berfungsi maka kita harus membuat object yang merupakan implementasi dari interface IComparer. Secara umum kita membuat satu object implementasi dari interface IComparer setiap object dalam Collection yang ingin diimplementasi artinya kalau mau sorting berdasarkan 3 field maka anda harus buat 3 field itupun dalam satu object yang di sorting bagaimana kalau object sorting lainnya ? oleh karena itu disini kita akan membuat object sorting yang nantinya akan dapat digunakan oleh object lainnya dengan memanfaatkan teknik Reflection.
Secara umum, object sorting yang akan dibuat dapat lihat seperti gambar dibawah ini

Ok, mari kita beda satu-satu. Object SortEnum adalah sebuah enum yang menyimpan nilai Asc dan Desc untuk keperluan mode sorting. SortEnum dideklarasikan sebagai berikut

    1 using System;

    2 

    3 namespace Sorting

    4 {

    5     public enum SortEnum

    6     {

    7         Asc,

    8         Desc

    9     }

   10 }

Sedangkan object CommonSort adalah implementasi interface IComparer yaitu  method Compare. Disini kita memanfaatkan reflection agar object CommonSort dapat digunakan oleh semua object, berikut ini implementasi object CommonSort

    1 using System;

    2 using System.Collections;

    3 using System.Reflection;

    4 

    5 namespace Sorting

    6 {

    7     public class CommonSort : IComparer

    8     {

    9         private string _column;

   10         private SortEnum _sort = SortEnum.Asc;

   11 

   12         public CommonSort(string column, SortEnum sort)

   13         {

   14             _column = column;

   15             _sort = sort;

   16         }

   17         #region IComparer Members

   18 

   19         public int Compare(object x, object y)

   20         {

   21             if (x == null && y == null)

   22             {

   23                 return 0;

   24             }

   25             else if (x == null && y != null)

   26             {

   27                 return (this._sort == SortEnum.Asc) ? -1 : 1;

   28             }

   29             else if (x != null && y == null)

   30             {

   31                 return (this._sort == SortEnum.Asc) ? 1 : -1;

   32             }

   33             else

   34             {

   35                 Type xType = x.GetType();

   36                 Type yType = y.GetType();

   37 

   38                 PropertyInfo xInfo = xType.GetProperty(_column,            

   39                                         BindingFlags.DeclaredOnly |

   40                                         BindingFlags.Default |

   41                                         BindingFlags.GetProperty |

   42                                         BindingFlags.Public |

   43                                         BindingFlags.Instance);

   44                 PropertyInfo yInfo = yType.GetProperty(_column,

   45                                         BindingFlags.DeclaredOnly |

   46                                         BindingFlags.Default |

   47                                         BindingFlags.GetProperty |

   48                                         BindingFlags.Public |

   49                                         BindingFlags.Instance);

   50 

   51                 object xVal = xInfo.GetValue(x, null);

   52                 object yVal = yInfo.GetValue(y, null);

   53 

   54                 return (this._sort == SortEnum.Asc) ?

   55                         ((IComparable)xVal).CompareTo(yVal) :

   56                         ((IComparable)yVal).CompareTo(xVal);

   57 

   58             }

   59         }

   60 

   61         #endregion

   62     }

   63 }

 
Ok, mari kita analisa code diatas. Mula-mula ketika object ini diinstansiasi maka nilai column dan mode sorting ditangkap dibagian constructornya

   12         public CommonSort(string column, SortEnum sort)

   13         {

   14             _column = column;

   15             _sort = sort;

   16         }

 
Ketika object ini dipakai dan dipanggil proses sorting maka method Compare akan terpanggil juga. Method ini akan mengembalikan nilai -1, 0 dan 1 artinya sebagai berikut
  • Jika bernilai -1 berarti nilai object x lebih kecil dibandingkan object y
  • Jika bernilai 0 berarti nilai object x sama dengan object y
  • Jika bernilai 1 berarti nilai object x lebih besar dibandingkan object y
Untuk mudahnya kita cek nilai NULL dari object  yang dibandingkan

   19         public int Compare(object x, object y)

   20         {

   21             if (x == null && y == null)

   22             {

   23                 return 0;

   24             }

   25             else if (x == null && y != null)

   26             {

   27                 return (this._sort == SortEnum.Asc) ? -1 : 1;

   28             }

   29             else if (x != null && y == null)

   30             {

   31                 return (this._sort == SortEnum.Asc) ? 1 : -1;

   32             }

   33             else

 
Jika memang object x dan y itu tidak NULL maka kita harus compare nilai propertie dimana nama propertie sudah didefinisikan oleh variable _column. Untuk mendapatkan nilai properties (yg didefnisiakn oleh _column) maka kita dapat memanfaatkan Reflection, cek code dibawah ini untuk cara dapat nilainya

   35                 Type xType = x.GetType();

   36                 Type yType = y.GetType();

   37 

   38                 PropertyInfo xInfo = xType.GetProperty(_column,            

   39                                         BindingFlags.DeclaredOnly |

   40                                         BindingFlags.Default |

   41                                         BindingFlags.GetProperty |

   42                                         BindingFlags.Public |

   43                                         BindingFlags.Instance);

   44                 PropertyInfo yInfo = yType.GetProperty(_column,

   45                                         BindingFlags.DeclaredOnly |

   46                                         BindingFlags.Default |

   47                                         BindingFlags.GetProperty |

   48                                         BindingFlags.Public |

   49                                         BindingFlags.Instance);

   50 

   51                 object xVal = xInfo.GetValue(x, null);

   52                 object yVal = yInfo.GetValue(y, null);

   53 

   54                 return (this._sort == SortEnum.Asc) ?

   55                         ((IComparable)xVal).CompareTo(yVal) :

   56                         ((IComparable)yVal).CompareTo(xVal);

 
Selanjutnya kita akan menggunakan didalam code. Mula-mula kita deklarasikan object ArrayList dan kemudian kita isi nilainya dengan object Employee

   13         private void InitData()

   14         {

   15             _list.Clear();

   16             for (int i = 0; i < 5; i++)

   17             {

   18                 Employee obj = new Employee();

   19                 obj.Id = i + 1;

   20                 obj.FirstName = "First" + (i + 1);

   21                 obj.LastName = "Last" + (i + 1);

   22                 obj.Address = "Jalan ABC No " + (i + 1);

   23                 obj.City = "Kota" + (i + 1);

   24 

   25                 _list.Add(obj);

   26             }

   27         }

 
Sedangkan proses sorting kita buat suatu method dengan inputan nama column dan mode sorting nya.

   44         private void ShowData(string column, SortEnum sort)

   45         {

   46             _list.Sort(new CommonSort(column, sort));

   47 

   48             Console.WriteLine("Id\tFirstName\tLastName\tAddress\tCity");

   49             for (int i = 0; i < _list.Count; i++)

   50             {

   51                 Employee obj = (Employee)_list[ i];

   52                 Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",

   53                                 obj.Id,

   54                                 obj.FirstName,

   55                                 obj.LastName,

   56                                 obj.Address,

   57                                 obj.City);

   58             }

   59         }

Pada code diatas, proses sorting sendiri terjadi ketikan object ArrayList memanggil method Sort

   46             _list.Sort(new CommonSort(column, sort));

 
Secara keseluruhan pemanggilnya code sebagai berikut:

   77         public void Perform()

   78         {

   79             Console.WriteLine("Initialize data");

   80             InitData();

   81 

   82             Console.WriteLine("Sorting by Id & ASC");

   83             ShowData("Id", SortEnum.Asc);

   84             Console.WriteLine("");

   85 

   86             Console.WriteLine("Sorting by FirstName & DESC");

   87             ShowData("FirstName", SortEnum.Desc);

   88 

   89         }

 
Diatas diatas, melakukan sorting dengan Propertie Id & by ASC dan selanjutnya juga melakukan sorting by Propertie FirstName dan by DESC. Berikut ini hasil eksekusi sorting pada Employee Collection (Non Generics Collection) 
Contoh output untuk sortin non generics collection dapat dilihat pada gambar dibawah ini
Sorting pada Generics Collection
Untuk sorting pada Generics Collection, pada hakikatnya sama hanya saja object sorting harus berbentuk Generics Class dan implementasi dari Generics Interface IComparer<T> lihat gambar dibawah ini:
Sedangkan implementasi dari method Compare itu adalah sama dengan yang sebelumnya. Berikut ini implementasinya:

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Reflection;

    4 

    5 namespace Sorting

    6 {

    7     public class CommontSortGenerics<T> : IComparer<T>

    8     {

    9         private string _column;

   10         private SortEnum _sort = SortEnum.Asc;

   11 

   12         public CommontSortGenerics(string column, SortEnum sort)

   13         {

   14             _column = column;

   15             _sort = sort;

   16         }

   17         #region IComparer<T> Members

   18 

   19         public int Compare(T x, T y)

   20         {

   21             if (x == null && y == null)

   22             {

   23                 return 0;

   24             }

   25             else if (x == null && y != null)

   26             {

   27                 return (this._sort == SortEnum.Asc) ? -1 : 1;

   28             }

   29             else if (x != null && y == null)

   30             {

   31                 return (this._sort == SortEnum.Asc) ? 1 : -1;

   32             }

   33             else

   34             {               

   35                 Type xType = x.GetType();

   36                 Type yType = y.GetType();

   37 

   38                 PropertyInfo xInfo = xType.GetProperty(_column,

   39                                         BindingFlags.DeclaredOnly |

   40                                         BindingFlags.Default |

   41                                         BindingFlags.GetProperty |

   42                                         BindingFlags.Public |

   43                                         BindingFlags.Instance);

   44                 PropertyInfo yInfo = yType.GetProperty(_column,

   45                                         BindingFlags.DeclaredOnly |

   46                                         BindingFlags.Default |

   47                                         BindingFlags.GetProperty |

   48                                         BindingFlags.Public |

   49                                         BindingFlags.Instance);

   50 

   51                 object xVal = xInfo.GetValue(x, null);

   52                 object yVal = yInfo.GetValue(y, null);

   53 

   54                 return (this._sort == SortEnum.Asc) ?

   55                         ((IComparable)xVal).CompareTo(yVal) :

   56                         ((IComparable)yVal).CompareTo(xVal);

   57 

   58             }

   59         }

   60 

   61         #endregion

   62     }

   63 }

 
Sedangkan cara pakainya,mula-mulai kita deklarasikan object Generics Collection misalkan List<Employee> dan kita isi nilai object Employee nya.

   28         private void InitDataForGenerics()

   29         {

   30             _listGenerics.Clear();

   31             for (int i = 0; i < 5; i++)

   32             {

   33                 Employee obj = new Employee();

   34                 obj.Id = i + 1;

   35                 obj.FirstName = "First" + (i + 1);

   36                 obj.LastName = "Last" + (i + 1);

   37                 obj.Address = "Jalan ABC No " + (i + 1);

   38                 obj.City = "Kota" + (i + 1);

   39 

   40                 _listGenerics.Add(obj);

   41             }

   42         }

Sedangkan proses sorting sebagai berikut:

   60         private void ShowDataForGenerics(string column, SortEnum sort)

   61         {

   62             _listGenerics.Sort(new CommontSortGenerics<Employee>(column, sort));          

   63 

   64             Console.WriteLine("Id\tFirstName\tLastName\tAddress\tCity");

   65             for (int i = 0; i < _listGenerics.Count; i++)

   66             {

   67                 Employee obj = _listGenerics[ i];

   68                 Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",

   69                                 obj.Id,

   70                                 obj.FirstName,

   71                                 obj.LastName,

   72                                 obj.Address,

   73                                 obj.City);

   74             }

   75         }

 
Sedangkan penggunaannya sebagai berikut:

   91         public void PerformForGenerics()

   92         {

   93             Console.WriteLine("Initialize data");

   94             InitDataForGenerics();

   95 

   96             Console.WriteLine("Sorting by Id & ASC");

   97             ShowDataForGenerics("Id", SortEnum.Asc);

   98             Console.WriteLine("");

   99 

  100             Console.WriteLine("Sorting by FirstName & DESC");

  101             ShowDataForGenerics("FirstName", SortEnum.Desc);

  102 

  103         }

 
Contoh hasil output dari sorting generics collection:
Source Code
Share this post: | | | |
Published Tuesday, November 28, 2006 2:31 PM by Agus Kurniawan

Comments

# re: #Computing is Fun : Working with Sorting in C#

Tuesday, November 28, 2006 3:36 PM by adrian

Hehe, kodenya ada yang ditranslate jadi emoticon tuh... :))

Matikan sebelum bermasalah...

# re: #Computing is Fun : Working with Sorting in C#

Tuesday, November 28, 2006 3:49 PM by arnoldwiliem

tiny correction

baik para *scientist* maupun business dev

# re: #Computing is Fun : Working with Sorting in C#

Wednesday, November 29, 2006 11:17 AM by agusto

Tapi mas AK sortingnya cuman untuk satu column / field doang yach, kalo multiple column gimana. Saya kemarin ada buat juga sorting kyk yang py mas Ak tadi untuk griedview nya, tapi waktu class itu mau di pake di component one untuk aggregate, saya tidak pake karena data nya kudu di sorting lebih dari satu field, jadi nya saya pake datatable aja untuk sorting.

# re: #Computing is Fun : Working with Sorting in C#

Wednesday, November 29, 2006 12:33 PM by agusto

Mas Ak, kalo sorting lebih dari 1 column, cara nya gimana yach. Kemarin saya juga buat coding sorting collection utk gridviewnya, tapi waktu

yang untuk component one utk aggregate itu saya kudu sorting lebih dari 1 column, jadi nya saya kembali ke datatable dan di sort di sana

# re: #Computing is Fun : Working with Sorting in C#

Wednesday, November 29, 2006 1:53 PM by Agus Kurniawan

Kalau mau lebih dari 1 column, maka dibagian constructor kau passing ArrayList/List<T> yang berisi string dari column yang mau dipassing. Kemudian dibagian implementasi method Compare maka kau lakukan compare dengan kondisi AND ;)..gampang kan ? sample code nya nanti saya coba provide kalau ada waktu sekalian update artikelnya

# re: #Computing is Fun : Working with Sorting in C#

Friday, December 01, 2006 8:21 PM by agusto

Hemmm oke dech Mas AK, saya tunggu update article nya, kalo project sich udah kelar dgn kalo yang master table saya pake sorting collection, cuman waktu untuk component one saya pake datatable.

Lumayan untuk menambah referensi coding lagi.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:
Powered by Community Server (Commercial Edition), by Telligent Systems