C# 集合排序



一個集合可否排序,要看系統知不知道排序的規則,像內建的系統類型,int ,string,short,decimal這些,系統知道怎麼排序,而如果一個集合裏面放置的是自定義類型,比如自己定義了一個Product類型,要把它排序,系統是不知道怎麼辦的。

 

那麼,如何告知系統排序的規則呢?有以下幾種方法:

 

1:對類實現IComparable接口,示例如下:

 

 

代碼1
複製代碼
1 using System; 2  using System.Collections.Generic; 3  using System.Linq; 4  using System.Text; 5 6  namespace SortTeset 7 { 8 class Product :IComparable 9 { 10 public string Name { get; private set; } 11 public decimal Price { get; private set; } 12 13 public Product(string name, decimal price) 14 { 15 Name = name; 16 Price = price; 17 } 18 19 public Product() { } 20 21 public static List<Product> GetSampleProduct() 22 { 23 return new List<Product> 24 { 25 new Product{Name="Watch",Price=12345.56m}, 26 new Product{Name="Knife",Price=224.50m}, 27 new Product{Name="Rope",Price=12.50m}, 28 new Product{Name="ETorch",Price=58.5m} 29 }; 30 } 31 32 public override string ToString() 33 { 34 return string.Format("{0} : {1}", Name, Price); 35 } 36 37 int IComparable.CompareTo(object obj) 38 { 39 Product temp = (Product)obj; 40 return this.Name.CompareTo(temp.Name); 41 } 42 43 } 44 45 class Program 46 { 47 static void Main(string[] args) 48 { 49 List<Product> ProductSample = Product.GetSampleProduct(); 50 foreach (Product tmp in ProductSample) 51 { 52 Console.WriteLine(tmp); 53 } 54 55 Console.WriteLine(); 56 57 ProductSample.Sort(); 58 59 foreach (Product tmp in ProductSample) 60 { 61 Console.WriteLine(tmp); 62 } 63 } 64 } 65 }
複製代碼

 

 

其中最主要的是這句:

   class Product :IComparable

跟這句:

    int IComparable.CompareTo(object obj)
        {
            Product temp = (Product)obj;
            return this.Name.CompareTo(temp.Name);
        }

 

就是實現了IComparable.CompareTo()這個方法。然後就可以直接調用 SomeProductList.Sort();方法來進行排序。

 

2:指定IComparer  類的對象。

 

 

代碼3
複製代碼
1 using System; 2  using System.Collections.Generic; 3  using System.Linq; 4  using System.Text; 5 6  namespace SortTeset2 7 { 8 class Product 9 { 10 public string Name { get; private set; } 11 public decimal Price { get; private set; } 12 13 public Product(string name, decimal price) 14 { 15 Name = name; 16 Price = price; 17 } 18 19 public Product() { } 20 21 public static List<Product> GetSampleProduct() 22 { 23 return new List<Product> 24 { 25 new Product{Name="Watch",Price=12345.56m}, 26 new Product{Name="Knife",Price=224.50m}, 27 new Product{Name="Rope",Price=12.50m}, 28 new Product{Name="ETorch",Price=58.5m} 29 }; 30 } 31 32 public override string ToString() 33 { 34 return string.Format("{0} : {1}", Name, Price); 35 } 36 } 37 38 39 class ProductNameComparer : IComparer<Product> 40 { 41 public int Compare(Product first, Product second) 42 { 43 return first.Name.CompareTo(second.Name); 44 } 45 } 46 47 class Program 48 { 49 static void Main(string[] args) 50 { 51 List<Product> ProductSample = Product.GetSampleProduct(); 52 foreach (Product tmp in ProductSample) 53 { 54 Console.WriteLine(tmp); 55 } 56 57 Console.WriteLine(); 58 59 ProductSample.Sort(new ProductNameComparer()); 60 61 foreach (Product tmp in ProductSample) 62 { 63 Console.WriteLine(tmp); 64 } 65 } 66 } 67 } 68  
複製代碼

 

 

這兒我們新定義了一個類:ProductNameComparer,這個類實現了泛型接口:IComparer<Product>,然後在

ProductSample.Sort(new ProductNameComparer());

語句中我們提供了一個比較器對象。

 

這種方法看上去不如直接實現ICompareable接口來得簡潔。

 

這種方法可以用匿名方法進行改進:

 

 

代碼4
複製代碼
1 using System; 2  using System.Collections.Generic; 3  using System.Linq; 4  using System.Text; 5 6  namespace SortTeset3 7 { 8 class Product 9 { 10 public string Name { get; private set; } 11 public decimal Price { get; private set; } 12 13 public Product(string name, decimal price) 14 { 15 Name = name; 16 Price = price; 17 } 18 19 public Product() { } 20 21 public static List<Product> GetSampleProduct() 22 { 23 return new List<Product> 24 { 25 new Product{Name="Watch",Price=12345.56m}, 26 new Product{Name="Knife",Price=224.50m}, 27 new Product{Name="Rope",Price=12.50m}, 28 new Product{Name="ETorch",Price=58.5m} 29 }; 30 } 31 32 public override string ToString() 33 { 34 return string.Format("{0} : {1}", Name, Price); 35 } 36 } 37 38 class Program 39 { 40 static void Main(string[] args) 41 { 42 List<Product> ProductSample = Product.GetSampleProduct(); 43 foreach (Product tmp in ProductSample) 44 { 45 Console.WriteLine(tmp); 46 } 47 48 Console.WriteLine(); 49 50 ProductSample.Sort(delegate(Product first, Product second) 51 { 52 return first.Name.CompareTo(second.Name); 53 }); 54 55 foreach (Product tmp in ProductSample) 56 { 57 Console.WriteLine(tmp); 58 } 59 } 60 } 61 } 62  
複製代碼

 

 

這一次,不用定義那個類,然後使用它的方法了,而是直接填充delegate接口。

 

這種方法還可以進一步用Lambda表達式改進,如下:

 

 

代碼5
複製代碼
1 using System; 2  using System.Collections.Generic; 3  using System.Linq; 4  using System.Text; 5 6  namespace SortTeset4 7 { 8 class Product 9 { 10 public string Name { get; private set; } 11 public decimal Price { get; private set; } 12 13 public Product(string name, decimal price) 14 { 15 Name = name; 16 Price = price; 17 } 18 19 public Product() { } 20 21 public static List<Product> GetSampleProduct() 22 { 23 return new List<Product> 24 { 25 new Product{Name="Watch",Price=12345.56m}, 26 new Product{Name="Knife",Price=224.50m}, 27 new Product{Name="Rope",Price=12.50m}, 28 new Product{Name="ETorch",Price=58.5m} 29 }; 30 } 31 32 public override string ToString() 33 { 34 return string.Format("{0} : {1}", Name, Price); 35 } 36 } 37 38 class Program 39 { 40 static void Main(string[] args) 41 { 42 List<Product> ProductSample = Product.GetSampleProduct(); 43 foreach (Product tmp in ProductSample) 44 { 45 Console.WriteLine(tmp); 46 } 47 48 Console.WriteLine(); 49 50 ProductSample.Sort((first,second)=>first.Name.CompareTo(second.Name)); 51 52 foreach (Product tmp in ProductSample) 53 { 54 Console.WriteLine(tmp); 55 } 56 } 57 } 58 } 59  
複製代碼

 

 

變態的是,還可以進一步改進,使用擴展方法,如下:

 

 

代碼6
複製代碼
1 using System; 2  using System.Collections.Generic; 3  using System.Linq; 4  using System.Text; 5 6  namespace SortTeset5 7 { 8 class Product 9 { 10 public string Name { get; private set; } 11 public decimal Price { get; private set; } 12 13 public Product(string name, decimal price) 14 { 15 Name = name; 16 Price = price; 17 } 18 19 public Product() { } 20 21 public static List<Product> GetSampleProduct() 22 { 23 return new List<Product> 24 { 25 new Product{Name="Watch",Price=12345.56m}, 26 new Product{Name="Knife",Price=224.50m}, 27 new Product{Name="Rope",Price=12.50m}, 28 new Product{Name="ETorch",Price=58.5m} 29 }; 30 } 31 32 public override string ToString() 33 { 34 return string.Format("{0} : {1}", Name, Price); 35 } 36 } 37 38 class Program 39 { 40 static void Main(string[] args) 41 { 42 List<Product> ProductSample = Product.GetSampleProduct(); 43 foreach (Product tmp in ProductSample) 44 { 45 Console.WriteLine(tmp); 46 } 47 48 Console.WriteLine(); 49 50 foreach (Product tmp in ProductSample.OrderBy(p=>p.Name)) 51 { 52 Console.WriteLine(tmp); 53 } 54 } 55 } 56 }
複製代碼

 

 

“這裏似乎調用了一個OrderBy方法,但查閱一下MSDN,就會發現這個方法在List<Product>中根本不存在。之所以能調用它,是由於存在一個擴展方法。這裏實際不再是"原地"對列表進行排序,而只是按特定的順序獲取列表的內容。有的時候,你需要更改實際的列表;但有的時候,沒有任何副作用的排序顯得更"善解人意"。重點在於,現在的寫法更簡潔,可讀性更好(當然是在你理解了語法之後)。我們的想法是"列表按名稱排序",現在的代碼正是這樣做的。並不是"列表通過將一個產品的名稱與另一個產品的名稱進行比較來排序",就像C# 2代碼所做的那樣。也不是使用知道如何將一個產品與另一個產品進行比較的另一個類型的實例來按名稱排序。這種簡化的表達方式是C# 3的核心優勢之一。既然單獨的數據查詢和操作是如此的簡單,那麼在執行更大規模的數據處理時,仍然可以保持代碼的簡潔性和可讀性,這進而鼓勵開發者以一種"以數據爲中心"的方式來觀察世界。”

 

最後這兩步的語法,絕對是一個會用其它語言比如C/C++,VB的人所無法明白的,C#進化速度真是快。。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章