在數組或者集合中對自定義類型進行排序分為兩種方法。
1.如果這個自定義類型是自己定義編寫的,那么我可以使它繼承ICompareable<T>接口,實現其中的CompareTo(Object)方法。然后直接Array.Sort(排序對象數組)對其進行排序。
1 class Book: IComparable<Book> 2 { 3 //defined name and number for book 4 public string BookName { get; set; } 5 public string BookNo { get; set; } 6 // implement the CompareTo method 7 public int CompareTo(Book other) 8 { 9 if (other == null) throw new ArgumentNullException("other"); 10 // compare to BookNo 11 return this.BookNo.CompareTo(other.BookNo); 12 } 13 }
我自定義了一個Book類型。有BookName和BookNo屬性。我使它繼承了ICompareable<Book>接口。並且實現了CompareTo(Book)方法。這樣,我就可以直接用Array.Sort()對
這個數組按BookNo進行排序。
1 static void test2() 2 { 3 Book[] bookArray = { 4 new Book{BookName = "AAA",BookNo = "0001"}, 5 new Book{BookName = "DDD",BookNo = "0004"}, 6 new Book{BookName = "CCC",BookNo = "0003"}, 7 new Book{BookName = "BBB",BookNo = "0002"}, 8 }; 9 Array.Sort(bookArray); 10 foreach (Book item in bookArray) 11 { 12 Console.WriteLine("BookName = \"{0}\"; BookNo = \"{1}\".",item.BookName,item.BookNo); 13 } 14 15 }
輸出結果:
BookName = "AAA"; BookNo = "0001". BookName = "BBB"; BookNo = "0002". BookName = "CCC"; BookNo = "0003". BookName = "DDD"; BookNo = "0004".
2.如果這個自定義類型不是自己編寫的,是別人已經編寫好的的一個類型,我不能修改這個類型。或者我想按照BookName排序,但是還不能修改現有的Book類該怎么辦?
我們可以對這個類型進行包裝。
1 class Person 2 { 3 public string PersonName { get; set; } 4 public string PersonAge {get;set;} 5 }
Person這個類型沒有繼承ICompare接口。這個類不能修改,但是我還要對PersonAge進行排序。
我自己創建一個PersonCompare類,它實現了ICompare<T>接口,我把排序規則寫在這個類中。
1 class PersonCompare : IComparer<Person> 2 { 3 public int Compare(Person x, Person y) 4 { 5 if (x == null || y == null) throw new ArgumentNullException("argument error."); 6 return x.PersonAge.CompareTo(y.PersonAge); //sort rule 7 } 8 }
測試:
1 static void test3() 2 { 3 Person[] personArray = { 4 new Person{PersonName = "AAA",PersonAge = "23"}, 5 new Person{PersonName = "EEE",PersonAge = "25"}, 6 new Person{PersonName = "CCC",PersonAge = "24"}, 7 new Person{PersonName = "FFF",PersonAge = "26"}, 8 }; 9 Array.Sort(personArray,new PersonCompare());//second parameter is sort rule 10 foreach(Person item in personArray) 11 { 12 Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge); 13 } 14 }
輸出結果:
PersonName = "AAA"; PersonAge = "23". PersonName = "CCC"; PersonAge = "24". PersonName = "EEE"; PersonAge = "25". PersonName = "FFF"; PersonAge = "26".
擴展:
如果我想對指定的屬性進行排序怎么辦?比如有的同事需要用PersonAge進行排序,有的需要使用PersonName進行排序。這種需求很常見。我們修改下PersonCompare方法。
為了使代碼更加的規范。我建議以Person的屬性為基礎創建一個枚舉。這個enum控制着我要按照那個屬性進行排序。
1 enum PersonType 2 { 3 PersonName, 4 PersonAge 5 }
我們需要PersonType作為參數傳遞給PersonCompare。以實現根據需求來定制排序規則。
class PersonCompare : IComparer<Person> { private PersonType useType; public PersonCompare(PersonType pt) { this.useType = pt; } public int Compare(Person x, Person y) { if (x == null || y == null) throw new ArgumentNullException("argument error."); //return x.PersonAge.CompareTo(y.PersonAge); switch (useType){ case PersonType.PersonAge: return x.PersonAge.CompareTo(y.PersonAge); case PersonType.PersonName: return x.PersonName.CompareTo(y.PersonName); default : throw new ArgumentNullException("Doesn't contain this type."); } } }
測試:
1 static void test3() 2 { 3 Person[] personArray = { 4 new Person{PersonName = "AAA",PersonAge = "23"}, 5 new Person{PersonName = "EEE",PersonAge = "25"}, 6 new Person{PersonName = "CCC",PersonAge = "23"}, 7 new Person{PersonName = "FFF",PersonAge = "26"}, 8 }; 9 Array.Sort(personArray,new PersonCompare(PersonType.PersonAge));// sort by age 10 foreach(Person item in personArray) 11 { 12 Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge); 13 } 14 Console.WriteLine("---------------------------------------------------"); 15 Array.Sort(personArray, new PersonCompare(PersonType.PersonName)); // sort by name 16 foreach (Person item in personArray) 17 { 18 Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge); 19 } 20 }
輸出結果:
PersonName = "CCC"; PersonAge = "23". PersonName = "AAA"; PersonAge = "23". PersonName = "EEE"; PersonAge = "25". PersonName = "FFF"; PersonAge = "26". --------------------------------------------------- PersonName = "AAA"; PersonAge = "23". PersonName = "CCC"; PersonAge = "23". PersonName = "EEE"; PersonAge = "25". PersonName = "FFF"; PersonAge = "26".
總結:
其實數組和集合的排序一樣。如果對自己定義的類型數組或者集合排序就用IComareable<T>。如果要對已有的類型數組或者集合排序就用IComare<T>.