在数组或者集合中对自定义类型进行排序分为两种方法。
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>.