在数组或者集合中对自定义类型进行排序分为两种方法。
1.如果这个自定义类型是自己定义编写的,那么我可以使它继承ICompareable<T>接口,实现其中的CompareTo(Object)方法。然后直接Array.Sort(排序对象数组)对其进行排序。
1 class Book: IComparable2 { 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 BookNo11 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 Person2 {3 public string PersonName { get; set; }4 public string PersonAge { get;set;}5 }
Person这个类型没有继承ICompare接口。这个类不能修改,但是我还要对PersonAge进行排序。
我自己创建一个PersonCompare类,它实现了ICompare<T>接口,我把排序规则写在这个类中。
1 class PersonCompare : IComparer2 {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 rule7 }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 rule10 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 PersonType2 {3 PersonName,4 PersonAge5 }
我们需要PersonType作为参数传递给PersonCompare。以实现根据需求来定制排序规则。
class PersonCompare : IComparer{ 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 age10 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 name16 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>.