C#排序比较
与C#定义了相等性比较规范一样,C#也定义了排序比较规范,以确定一个对象与另一个对象的先后顺序。排序规范如下
- IComparable接口(包括IComparable接口和IComparable<T>接口)
- >和<运算符
当需要实现排序算法时,使用IComparable接口。在下面的例子中,Array.Sort静态方法可以调用,是因为System.String类实现了IComparable接口。
string[] colors={"Green", "Red", "Blue"};
Array.Sort(colors)
foreach(string c in colors)
Console.Write(c+ " ");
而<和>运算符比较特殊,因为他们一般用于比较数字类型。因为大于和小于运算符会被静态地解析,因此它们“产生”出高效的代码,适用于复杂计算的场景。
.NET Framework还提供了插件式的排序协议--IComparer接口。IComparable接口与IComparer接口的差别类似与IEquatable和IEqualityComparer接口 (关于IEqutable接口和IEqualityComparer接口,请参考C#相等性:http://www.cnblogs.com/yang_sy/p/3582946.html)
1. IComparable接口
IComparable接口的定义如下
public interface IComparable
int CompareTo(Object obj);
}
public interface IComparable<in T>
{
int CompareTo(T other);
}
这两个接口定义了相同的功能。对于值类型,IComparable<T>接口效率高于ICompare接口。上面的两个接口的CompareTo方法都按照下面的方式运行:
- 如果a排在b后面,那么a.CompareTo(b)返回1
- 如果a和不一样,那么返回0
- 如果a排在不前面,那么返回-1
我们来看下面的示例代码:
IList<Staff> staffs = new List<Staff>
{
new Staff{FirstName="AAA", Title="Manager", Dept="Sale"},
new Staff{FirstName="BBB", Title="Accountant", Dept="Finance"},
new Staff{FirstName="CCC", Title="Accountant", Dept="Finance"},
}; Console.WriteLine("BBB".CompareTo(staffs[0].FirstName)); // 1
Console.WriteLine("BBB".CompareTo(staffs[1].FirstName)); // 0
Console.WriteLine("BBB".CompareTo(staffs[2].FirstName)); // -1
C#的大部分基本类型都实现了IComparable接口和IComparable<T>接口。很多自定义类型同样也实现了该接口,这样便于排序。
IComarable与Equals
假设一个类型重写了Equals方法并实现了IComparable接口。那么你肯定希望当Equals返回true时,CompareTo应当返回0。而Equals返回false时,CompareTo可以返回任何值。
换句话说,相等性比对比性更严格;反之则不会。因此,当CompareTo说“两个对象相等”时,Equals会说“这两个对象不一定相等”。一个很好的例子来自System.String类。String.Equals方法和==运算符使用序号排序规则比较字符串--也就是通过每个字符的Unicode的值进行排序。而String.CompareTo方法,却使用不那么严格的基于文化区域(culture-dependent)进行比较。对于大多数计算机,字符ǖ和ṻ,Equals返回False,而CompareTo返回0
你可以实现通过IComparer接口,从而完成特定的排序算法。自定义IComparer接口的实现,进一步加大了CompareTo和Equals方法之间的差异。比如不区分大小写的字符串比较器,对于A和a,将返回0. 这也从反面印证了,ComparTo方法不如Equals方法严格。
2. <和>运算符
一些类型,定义了<和>运算符,比如:
bool after2010 = DateTime.Now > new DateTime(2010, 1, 1);
Console.WriteLine(after2010);
当实现<和>运算符之后,你需要保证<和>运算符与IComparable接口保持一致。这也是.NET Framework的标准。
同样地,当一个类型重载了<和>运算符,那么也要求实现IComparable接口,而反之则不需要。实际上,大多数.NET类型实现了IComparable接口,并没有重载<和>运算符。这(排序比较)与相等性比较不一样:
- 在实现相等性比较时,如果重载了Equals方法,那么一般都重载==运算符
- 而在实现排序性比较时,如果实现了CompareTo方法,一般不要求重载<运算符和>运算符
一般地,只有在下面的情形中,才需要重载<运算符和>运算符:
- 一个类型本身包含大于和小于这样的概念
- 执行先后顺序比较的方式是唯一的
- 结果不会随文化区域(Cultures)变化而变化
System.Stirng类型不满足最后一条,因此string不支持>操作和<操作。因此 “beck” > “Anne”,编译时会抛出错误。
3. 实现IComparable接口
下面的实例代码中,结构Note表示一个音乐的注释,它实现了IComparable接口,还重载了<运算符和>运算符。为了实例的完整性,我们还重写了Equals和GetHashCode方法,以及重载了==和!=运算符,通过这个例子,你可以全面的了解排序比较。
internal struct Note : IComparable, IComparable<Note>, IEquatable<Note>
{ private int semitonesFromA;
public int SemitonesFromA
{
get { return semitonesFromA; }
} public Note(int semitonesFromA)
{
this.semitonesFromA = semitonesFromA;
} // generic IComparable<T>
public int CompareTo(Note other)
{
if (Equals(other))
return 0;
return SemitonesFromA.CompareTo(other.SemitonesFromA);
} // non-generic IComaparable
public int IComparable.CompareTo(object other)
{
if (!(other is Note))
throw new InvalidOperationException("CompareTo: Not a note");
return CompareTo((Note)other);
} public static bool operator <(Note n1, Note n2)
{
return n1.CompareTo(n2) < 0;
} public static bool operator >(Note n1, Note n2)
{
return n1.CompareTo(n2) > 0;
} // for IEquatable
public bool Equals(Note other)
{
return this.SemitonesFromA == other.SemitonesFromA;
} // override Object.Equals
public override bool Equals(object other)
{
if (!(other is Note))
throw new InvalidOperationException("CompareTo: Not a note");
return Equals((Note)other);
} public override int GetHashCode()
{
return SemitonesFromA.GetHashCode();
} public static bool operator ==(Note n1, Note n2)
{
return n1.Equals(n2);
} public static bool operator !=(Note n1, Note n2)
{
return !(n1 == n2);
}
}
C#排序比较的更多相关文章
- javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈
Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...
- iOS可视化动态绘制八种排序过程
前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...
- JavaScript实现常用的排序算法
▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...
- [C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序
用菜鸟的思维学习算法 -- 马桶排序.冒泡排序和快速排序 [博主]反骨仔 [来源]http://www.cnblogs.com/liqingwen/p/4994261.html 目录 马桶排序(令人 ...
- 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...
- 算法与数据结构(七) AOV网的拓扑排序
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
- 使用po模式读取豆瓣读书最受关注的书籍,取出标题、评分、评论、题材 按评分从小到大排序并输出到txt文件中
#coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...
- javascript排序
利用array中的sort()排序 w3cfunction sortNumber(a,b) { return a - b } var arr = new Array(6) arr[0] = " ...
- iOS自定义model排序
在开发过程中,可能需要按照model的某种属性排序. 1.自定义model @interface Person : NSObject @property (nonatomic,copy) NSStri ...
- Lucene4.4.0 开发之排序
排序是对于全文检索来言是一个必不可少的功能,在实际运用中,排序功能能在某些时候给我们带来很大的方便,比如在淘宝,京东等一些电商网站我们可能通过排序来快速找到价格最便宜的商品,或者通过排序来找到评论数最 ...
随机推荐
- 检查密码复杂度的C#正则表达式
在用户注册与修改.重置密码时,强制密码达到一定的复杂度,是减少盗号的有效措施之一. 而在代码中检查密码复杂度就需要用到正则表达式,比如要求密码必须包含数字.小写或大写字母.特殊字符.字符数在8-30之 ...
- (译)开发优秀的虚拟现实体验:从开发I Expect You to Die中总结的六个要点
这篇文章是我从网上找来的,我觉得他非常详细的解释了VR发展的需求和必要.我认为通过这篇文章可以让大家了解VR. 译者写在最前: 来到追光动画有好几个月了,抱歉这段时间也没有什么文章与大家分享,我现在在 ...
- 使用gdb调试Python进程
使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...
- 我所常用的ajax调用格式
ajax: $.ajax({ type: "post", datatype: "json", contentType: "appli ...
- hibernate主键生成策略(转载)
http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指 ...
- Redis教程(十):持久化详解
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/137.html 一.Redis提供了哪些持久化机制: 1). RDB持久化 ...
- 【原】关于使用Sklearn进行数据预处理 —— 缺失值(Missing Value)处理
关于缺失值(missing value)的处理 在sklearn的preprocessing包中包含了对数据集中缺失值的处理,主要是应用Imputer类进行处理. 首先需要说明的是,numpy的数组中 ...
- fir.im Weekly - 每个程序员都应当拥有的技能树
本周收集了一些优秀的 iOS & Android 开发资源和程序员 IT 技能拓展的 Tips. 知道创宇研发技能表 v3.0 作为程序员可能都听说过[知道创宇],他们是一家黑客文化浓厚的安全 ...
- iOS-OC内存管理
目标 1.[理解]内存管理 2.[掌握]第一个MRC程序 3.[掌握]内存管理的原则 4.[理解]野指针与僵尸对象 5.[理解]单个对象的内存管理 6.[理解]多个对象的内存管理 7.[掌握]set方 ...
- iOS数据持久化-OC
沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...