對集合元素進行排序是經常發生的事情,事實上大部分的集合類型都預設實現了Sort方法,進行其元素的排序操作。例如List<T>集合的Sort方法有:
public void Sort();public void Sort(Comparison<T> comparison);public void Sort(IComparer<T> comparer);public void Sort(int index, int count, IComparer<T> comparer);
在排序使用上,四個Sort是大同小異,唯一不同的是大部分情況下,排序的要求決定了我們不能完全滿足於預設排序的情況,因為Framework根本不清楚“你”排序的目的,例如:
BookStore bs = new BookStore{ Books = new List<Book> { new Book{ID = 1, Name="你必須知道的.NET", Price=69, PublishDate=DateTime.Parse("2008-3-30")}, new Book{ID = 2, Name="Silverlight完美征程", Price=75, PublishDate=DateTime.Parse("2009-4-30")}, new Book{ID =3, Name="部落格園精華集", Price=72, PublishDate=DateTime.Parse("2009-5-3")} }};實現自訂的排序演算法
如果需要對書店的書目進行排序,那麼在我們的小樣本中至少可以按照書名、書價和出版日期進行排序,因此.NET Framework在設計上為Sort提供了很好的擴充,通常情況下我們需要實現自訂的comparison和comparer,例如:
// Release : code01, 2009/04/12 // Author : Anytao, http://www.anytao.com // List : Protram.cs //02 Sort by custom comparison bs.Books.Sort((a, b) => { return a.Price.CompareTo(b.Price); }); foreach (var item in bs.Books) { Console.WriteLine(string.Format("{0}:{1}, {2}", item.Name, item.Price, item.PublishDate.ToString())); }
你看利用Lambda運算式實現一個Custom Comparison是何其簡單:
bs.Books.Sort((a, b) => { return a.Price.CompareTo(b.Price); });
輸出的結果為:
如果我們實現以出版日期進行排序的Custom Comparison,應該是這樣:
bs.Books.Sort((a, b) => { return a.PublishDate.CompareTo(b.PublishDate); });
排序的結果如我所願:
利用Lamdba運算式實現的Comparison變得非常簡單,優雅有度,我們迴歸複雜將Lamdba運算式解析為匿名方法(Anonymous Method):
// Release : code01, 2009/04/12 // Author : Anytao, http://www.anytao.com // List : Protram.cs//03 Sort by custom comparison: Anonymous Methodbs.Books.Sort(delegate(Book a, Book b){ return a.Price.CompareTo(b.Price);});
如果你對匿名方法還心存芥蒂,那麼我們迴歸Custom Comparison的最本源實現:
// Release : code01, 2009/04/12 // Author : Anytao, http://www.anytao.com // List : BookComparison.cspublic class BookComparison : IComparer<Book>{ public int Compare(Book x, Book y) { return x.Price.CompareTo(y.Price); }}
利用BookComparison 進行比較,
//04 Sort by custom comparison: BookComparisonbs.Books.Sort(new BookComparison().Compare);
輸出的結果和bs.Books.Sort((a, b) => { return a.Price.CompareTo(b.Price); });一樣,可謂皆大歡喜。
以自訂方式可以實現的更多的控制,例如我們重構BookComparison:
// Release : code01, 2009/04/12 // Author : Anytao, http://www.anytao.com // List : BookComparison.cspublic class BookComparison : IComparer<Book>{ private ComparisonType type; public BookComparison(ComparisonType type) { this.type = type; } public int Compare(Book x, Book y) { switch (this.type) { case ComparisonType.Price: return x.Price.CompareTo(y.Price); break; case ComparisonType.PublishDate: return x.PublishDate.CompareTo(y.PublishDate); break; default: break; } return 0; }}
添加一個ComparisonType結構,在BookComparson初始化時決定Comparison的方式:
//04 Sort by custom comparison: BookComparisonbs.Books.Sort(new BookComparison(ComparisonType.PublishDate).Compare);
結論
自訂Comparison為實現更好的Sort控制,提供了很好的擴充機制。在我們的實際應用中,對於例如BookStore這樣的具體應用而言,我更推薦以LINQ的OrderBy來實現,例如:
//05 Sort by Linqvar list = from c in bs.Books orderby c.PublishDate ascending select c;foreach (var item in list){ Console.WriteLine(string.Format("{0}:{1}, {2}", item.Name, item.Price, item.PublishDate.ToString()));}
orderby子句可以選擇任意的排序條件,同時ascending或者descending控制升序和降序。
何去何從,看官自評。