C#自定义类型数组排序
在数组或者集合中对自定义类型进行排序分为两种方法。
1.如果这个自定义类型是自己定义编写的,那么我可以使它继承ICompareable<T>接口,实现其中的CompareTo(Object)方法。然后直接Array.Sort(排序对象数组)对其进行排序。
class Book: IComparable<Book>
{
//defined name and number for book
public string BookName { get; set; }
public string BookNo { get; set; }
// implement the CompareTo method
public int CompareTo(Book other)
{
if (other == null) throw new ArgumentNullException("other");
// compare to BookNo
return this.BookNo.CompareTo(other.BookNo);
}
}
我自定义了一个Book类型。有BookName和BookNo属性。我使它继承了ICompareable<Book>接口。并且实现了CompareTo(Book)方法。这样,我就可以直接用Array.Sort()对
这个数组按BookNo进行排序。
static void test2()
{
Book[] bookArray = {
new Book{BookName = "AAA",BookNo = ""},
new Book{BookName = "DDD",BookNo = ""},
new Book{BookName = "CCC",BookNo = ""},
new Book{BookName = "BBB",BookNo = ""},
};
Array.Sort(bookArray);
foreach (Book item in bookArray)
{
Console.WriteLine("BookName = \"{0}\"; BookNo = \"{1}\".",item.BookName,item.BookNo);
} }
输出结果:
BookName = "AAA"; BookNo = "".
BookName = "BBB"; BookNo = "".
BookName = "CCC"; BookNo = "".
BookName = "DDD"; BookNo = "".
2.如果这个自定义类型不是自己编写的,是别人已经编写好的的一个类型,我不能修改这个类型。或者我想按照BookName排序,但是还不能修改现有的Book类该怎么办?
我们可以对这个类型进行包装。
class Person
{
public string PersonName { get; set; }
public string PersonAge {get;set;}
}
Person这个类型没有继承ICompare接口。这个类不能修改,但是我还要对PersonAge进行排序。
我自己创建一个PersonCompare类,它实现了ICompare<T>接口,我把排序规则写在这个类中。
class PersonCompare : IComparer<Person>
{
public int Compare(Person x, Person y)
{
if (x == null || y == null) throw new ArgumentNullException("argument error.");
return x.PersonAge.CompareTo(y.PersonAge); //sort rule
}
}
测试:
static void test3()
{
Person[] personArray = {
new Person{PersonName = "AAA",PersonAge = ""},
new Person{PersonName = "EEE",PersonAge = ""},
new Person{PersonName = "CCC",PersonAge = ""},
new Person{PersonName = "FFF",PersonAge = ""},
};
Array.Sort(personArray,new PersonCompare());//second parameter is sort rule
foreach(Person item in personArray)
{
Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge);
}
}
输出结果:
PersonName = "AAA"; PersonAge = "".
PersonName = "CCC"; PersonAge = "".
PersonName = "EEE"; PersonAge = "".
PersonName = "FFF"; PersonAge = "".
扩展:
如果我想对指定的属性进行排序怎么办?比如有的同事需要用PersonAge进行排序,有的需要使用PersonName进行排序。这种需求很常见。我们修改下PersonCompare方法。
为了使代码更加的规范。我建议以Person的属性为基础创建一个枚举。这个enum控制着我要按照那个属性进行排序。
enum PersonType
{
PersonName,
PersonAge
}
我们需要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.");
}
}
}
测试:
static void test3()
{
Person[] personArray = {
new Person{PersonName = "AAA",PersonAge = ""},
new Person{PersonName = "EEE",PersonAge = ""},
new Person{PersonName = "CCC",PersonAge = ""},
new Person{PersonName = "FFF",PersonAge = ""},
};
Array.Sort(personArray,new PersonCompare(PersonType.PersonAge));// sort by age
foreach(Person item in personArray)
{
Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge);
}
Console.WriteLine("---------------------------------------------------");
Array.Sort(personArray, new PersonCompare(PersonType.PersonName)); // sort by name
foreach (Person item in personArray)
{
Console.WriteLine("PersonName = \"{0}\"; PersonAge = \"{1}\".", item.PersonName, item.PersonAge);
}
}
输出结果:
PersonName = "CCC"; PersonAge = "".
PersonName = "AAA"; PersonAge = "".
PersonName = "EEE"; PersonAge = "".
PersonName = "FFF"; PersonAge = "".
---------------------------------------------------
PersonName = "AAA"; PersonAge = "".
PersonName = "CCC"; PersonAge = "".
PersonName = "EEE"; PersonAge = "".
PersonName = "FFF"; PersonAge = "".
总结:
其实数组和集合的排序一样。如果对自己定义的类型数组或者集合排序就用IComareable<T>。如果要对已有的类型数组或者集合排序就用IComare<T>.
C#自定义类型数组排序的更多相关文章
- 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)
1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...
- C#简单问题,不简单的原理:不能局部定义自定义类型(不含匿名类型)
今天在进行代码测试时发现,尝试在一个方法中定义一个委托,注意是定义一个委托,而不是声明一个委托变量,在编写的时候没有报错,VS也能智能提示,但在编译时却报语法不完整,缺少方括号,但实际查询并没有缺少, ...
- Struts2框架的自定义类型转换器
前言:对于java的基本数据类型及一些系统类(如Date类.集合类),Struts2提供了内置类型转换功能,但是也有一定的限制.所以就演示出自定义类型转换器 一.应用于局部类型转换器 eg.用户登录出 ...
- sruts2 自定义类型转换器
1.1.1 Struts2中自定义类型转换器:(了解) 类型转换的过程是双向的过程: JSP---->Action参数提交:String---Date. Action---->JSP ...
- 一个关于自定义类型作为HashMap的key的问题
在之前的项目需要用到以自定义类型作为HashMap的key,遇到一个问题:如果修改了已经存储在HashMap中的实例,会发生什么情况呢?用一段代码来试验: import java.util.HashM ...
- Struts2之自定义类型转换器
Struts2自定义类型转换器分为局部类型转换器和全局类型转换器 (1)局部类型转换器 如果页面传来一个参数reg.action?birthday=2010-11-12到后台action,然后属性用d ...
- [原创]java WEB学习笔记67:Struts2 学习之路-- 类型转换概述, 类型转换错误修改,如何自定义类型转换器
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 自定义类型转换器converter
作用:目前将日期转换成string,将string转换成我想要的类型 0509课件里讲 一.数据类型转换在web应用程序中,数据存在两个方向上的转换:1.当提交表单时 表单数据以字符串的形式提交 ...
- 用SQLData读写数据库自定义类型
如何读写自定义类型?SQLData是个很直观的解决办法 在oracle使用手册上找到了很好的资料 点击打开链接 http://docs.oracle.com/cd/B10501_01/java.920 ...
随机推荐
- [git 学习篇]自己在github创建一个远程服务器创库
现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举 ...
- AtCoder Petrozavodsk Contest 001
第一场apc,5H的持久战,我当然水几个题就睡了 A - Two Integers Time limit : 2sec / Memory limit : 256MB Score : 100 point ...
- poj 2499第K短路模板
第k*短路模板(单项边) #include <iostream> #include <cstdio> #include <algorithm> #include & ...
- map/set/object/array对比
map () { //数据结构横向对比, 增,查,改,删 let map = new Map() let array = [] //增 map.set('t',1) array.push({t:1}) ...
- 【Luogu】P3979遥远的国度(树链剖分)
题目链接 不会换根从暑假开始就困扰我了……拖到现在…… 会了还是很激动的. 换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚…… 设全树的集合为G,以root为根,u在 ...
- [HNOI2006]公路修建问题 (二分答案,并查集)
题目链接 Solution 二分答案+并查集. 由于考虑到是要求花费的最小值,直接考虑到二分. 然后对于每一个二分出来的答案,模拟 \(Kruskal\) 的过程再做一遍连边. 同时用并查集维护联通块 ...
- java面试题之数据基本类型各占几个字节
类型 位数 字节数 short 2*8 2 char 2*8 2 int 4*8 4 float 4*8 4 long 8*8 8 double 8*8 8
- webpack打包字体图标报错的解决办法
webpack打包字体图标需要两个加载器 url-loader 和 file-loader 另外 字体图标的引入方式 本来应该是 url("....") 这样的方式,但是w ...
- DispatcherServlet与ContextLoaderListener的对比
1. 从DispatcherServlet和ContextLoaderListener的初始化过程可以看出,二者分别会生成一个WebApplicationContext,且以不同的attrName注册 ...
- AC日记——一元三次方程求解 洛谷 P1024
题目描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...