.NET Framework System.Array.Sort 数组类,加深对 IComparer、IComparable 以及泛型委托、匿名方法、Lambda 表达式的理解
本文内容
- 自定义类
- Array.Sort
- 参考资料
System.Array.Sort 有很多对集合的操作,比如排序,查找,克隆等等,你可以利用这个类加深对 IComparer、IComparable 以及泛型委托、匿名方法、Lambda 表达式的理解。
下载 Demo
自定义类
自定义两个类:Person 和 PersonComparer 。后面会用到这两个类。
自定义 Person 类
Person 类有两个属性:FirstName 和 LastName,重构了 ToString 方法。该类还继承 IComparable 接口,实现了 CompareTo 方法,会在后面 Array.Sort 方法中用到。如下所示:
public class Person : IComparable
{
public Person()
{
}
public Person(string firstname, string lastname)
{
this.FirstName = firstname;
this.LastName = lastname;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
public int CompareTo(object obj)
{
Person other = obj as Person;
return this.LastName.CompareTo(other.LastName);
}
}
说明:CompareTo 方法,它提供了默认比较,按 LastName 升序排序。
自定义 PersonComparer 类
该类内部定义了一个比较类型,可以按 FirstName 或 LastName 比较,并且都是升序排序。PersonComparer 类同时继承 IComparer 接口的非泛型形式和泛型形式,实现了它们相应的 Compare 方法,该方法会在 Array.Sort 中用到。如下所示:
public class PersonComparer : IComparer, IComparer<Person>
{
public enum PersonCompareType
{
FirstName,
LastName
}
private PersonCompareType compareType;
public PersonComparer(PersonCompareType compareType)
{
this.compareType = compareType;
}
public int Compare(object x, object y)
{
Person p1 = x as Person;
Person p2 = y as Person;
switch (compareType)
{
case PersonCompareType.FirstName:
return p1.FirstName.CompareTo(p2.FirstName);
case PersonCompareType.LastName:
return p1.LastName.CompareTo(p2.LastName);
default:
throw new ArgumentException("unexpected compare type");
}
}
public int Compare(Person x, Person y)
{
Person p1 = x;
Person p2 = y;
switch (compareType)
{
case PersonCompareType.FirstName:
return p1.FirstName.CompareTo(p2.FirstName);
case PersonCompareType.LastName:
return p1.LastName.CompareTo(p2.LastName);
default:
throw new ArgumentException("unexpected compare type");
}
}
}
Array.Sort
Array.Sort 有 17 个“重载”,如下所示:
Sort(Array)
Sort(Array, Array)
Sort(Array, IComparer)
Sort(Array, Array, IComparer)
Sort(Array, Int32, Int32)
Sort(Array, Array, Int32, Int32)
Sort(Array, Int32, Int32, IComparer)
Sort(Array, Array, Int32, Int32, IComparer)
Sort<T>(T[])
Sort<T>(T[], IComparer<T>)
Sort<T>(T[], Comparison<T>)
Sort<T>(T[], Int32, Int32)
Sort<T>(T[], Int32, Int32, IComparer<T>)
Sort<TKey, TValue>(TKey[], TValue[])
Sort<TKey, TValue>(TKey[], TValue[], IComparer<TKey>)
Sort<TKey, TValue>(TKey[], TValue[], Int32, Int32)
Sort<TKey, TValue>(TKey[], TValue[], Int32, Int32, IComparer<TKey>)
从它们的参数,你可以先想象一下:
- 这些方法可以分成非泛型形式和泛型形式,也就是每个非泛型形式基本都会对应一个泛型形式;
- 如果我们要对一个集合排序,肯定是要比较的,并且默认排序,一般是升序,当然也可以是降序;
- 如果集合是字符串,那很好办,几乎不需要做什么;
- 可如果集合是对象,那我们就必须指定两个对象之间如何比较;
- 如果有两个集合,一个集合是当键,另一个集合是当值,用键为值排序,这当然也是可以的,比如 Sort<TKey, TValue>;
- 针对不同的场景,可以指定不同的比较方式,比如,参数中带 ICompare 的。可以指定按 LastName 升序或降序,或 FirstName 升序或降序 。
如果集合仅仅是字符串数组,那很好办,如下代码所示,按升序排序:
string[] names = { "Emerson Fittipaldi", "Niki Lauda", "Ayrton Senna", "Michael Schumacher" };
Array.Sort(names);
但外国人的姓在后面,要按我们的习惯如何按姓排序?字符串数组肯定不行,这就需要自定义的 Person 类了,假设有如下 Person 数组:
Person[] persons = {
new Person("Emerson", "Fittipaldi"),
new Person("Niki", "Lauda"),
new Person("Ayrton", "Senna"),
new Person("Michael", "Schumacher")
};
采用 Sort(Array) 这个方法,按姓的升序排序,如下代码所示:
Array.Sort(persons);
因为定义 Person 类时,继承了 IComparer 接口,并实现了 CompareTo 方法,里面规定了按姓 LastName 比较,并且是升序,所以 Array.Sort 方法就知道如何排序了。
如果有时需要按 FirstName 排序,有时用 LastName,怎么办?这就需要自定义的类 PersonComparer。采用 Sort(Array, IComparer) 这个方法,代码如下所示:
Array.Sort(persons, new PersonComparer(PersonComparer.PersonCompareType.FirstName));
Console.WriteLine("Sort By First Name:");
foreach (Person p in persons)
{
Console.WriteLine(" " + p);
}
Array.Sort(persons, new PersonComparer(PersonComparer.PersonCompareType.LastName));
Console.WriteLine("Sort By Last Name:");
foreach (Person p in persons)
{
Console.WriteLine(" " + p);
}
结果:
Sort By First Name:
Ayrton Senna
Emerson Fittipaldi
Michael Schumacher
Niki Lauda
Sort By Last Name:
Emerson Fittipaldi
Niki Lauda
Michael Schumacher
Ayrton Senna
如果我们事先未定义 PersonComparer 类,也没问题,可以采用 Sort<T>(T[], Comparison<T>) 这个方法,参数 Comparison<T> 是 .Net 提供的泛型委托,这意味着我们可以用匿名方法或 Lambda 表达式来规定 Person 如何比较,采用匿名方法如下所示:
Array.Sort(persons,
delegate(Person p1, Person p2)
{
return p1.FirstName.CompareTo(p2.FirstName);
});
Array.Sort(persons,
delegate(Person p1, Person p2)
{
return p1.LastName.CompareTo(p2.LastName);
});
或采用 Lambda 表达式形式:
Array.Sort(persons, (p1, p2) => p1.FirstName.CompareTo(p2.FirstName));
Array.Sort(persons, (p1, p2) => p1.LastName.CompareTo(p2.LastName));
如果有两个集合,让其中一个集合为另一个集合排序呢?若有两个 Person 集合,一模一样,只是一个当键,另一个当值,用键为值排序,如下代码所示:
Person[] personKeys = {
new Person("Emerson", "Fittipaldi"),
new Person("Niki", "Lauda"),
new Person("Ayrton", "Senna"),
new Person("Michael", "Schumacher")
};
Person[] personValues = {
new Person("Emerson", "Fittipaldi"),
new Person("Niki", "Lauda"),
new Person("Ayrton", "Senna"),
new Person("Michael", "Schumacher")
};
Array.Sort<Person, Person>(personKeys, personValues);
Array.Sort<Person, Person>(personKeys, personValues, new PersonComparer(PersonComparer.PersonCompareType.FirstName));
其中,
- Sort 有两个参数的泛型方法,personValues 会按 personKeys 的 LastName 按升序排序。这是默认的;
- Sort 有三个参数的泛型方法,personValues 会按 personKeys 的 FirstName 按升序排序。
Array 中的其他方法,像 BinarySearch、Find 相关和 indexOf 相关,跟 Sort 用法类似,因为它们的参数大都是 IComparer、IComparable 以及泛型委托。
参考资料
.NET Framework System.Array.Sort 数组类,加深对 IComparer、IComparable 以及泛型委托、匿名方法、Lambda 表达式的理解的更多相关文章
- C#高级编程笔记 (1至6章节)数组,类/方法/泛型
2.3变量 var 类型推断 type 类的分类 如:type nametype = name.GetType(); //取变量name的类型 const 常量 const int painame ...
- 【system.array】使用说明
对象:system.array 说明:提供一系列针对数组类型的操作 目录: 方法 返回 说明 system.array.join( array, separator ) [String] 将数组转换 ...
- 【java集合总结】-- 数组总结+自己封装数组类
一.前言 本篇文章总结目前学习的有关数组方面的知识,首先总结一下数组相关的核心概念,然后在封装一个自己的泛型动态数组类(ava已经封装的有现成的,自己封装只是为了加深理解),最后再学习解析下Array ...
- .NET 排序 Array.Sort<T> 实现分析
System.Array.Sort<T> 是.NET内置的排序方法, 灵活且高效, 大家都学过一些排序算法,比如冒泡排序,插入排序,堆排序等,不过你知道这个方法背后使用了什么排序算法吗? ...
- Java8 Collections.sort()及Arrays.sort()中Lambda表达式及增强版Comparator的使用
摘要:本文主要介绍Java8 中Arrays.sort()及Collections.sort()中Lambda表达式及增强版Comparator的使用. 不废话直接上代码 import com.goo ...
- java语言中的匿名类与lambda表达式介绍与总结 (Anonymous Classes and Lambda Expressions)
2017/6/30 转载写明出处:http://www.cnblogs.com/daren-lin/p/anonymous-classes-and-lambda-expressions-in-java ...
- Effective Java 第三版——42.lambda表达式优于匿名类
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- [ActionScript 3.0] 对数组中的元素进行排序Array.sort()的方法
对数组中的元素进行排序. 此方法按 Unicode 值排序. (ASCII 是 Unicode 的一个子集.) 默认情况下,Array.sort()按以下方式进行排序: 1. 排序区分大小写(Z优先于 ...
- Array(数组)对象-->sort() 方法
1.定义和用法 sort() 方法用于对数组的元素进行排序. 默认排序顺序为按字母升序. 语法: array.sort(sortfunction) 参数: sortfunction:规定排序顺序.必须 ...
随机推荐
- 《Go语言实战》摘录:7.1 并发模式 - runner
7.1 并发模式 - runner
- C#远程调用技术WebService修炼手册
一.课程介绍 一位伟大的讲师曾经说过一句话:事物存在即合理!意思就是说:任何存在的事物都有其存在的原因,存在的一切事物都可以找到其存在的理由,我们应当把焦点放在因果关联的本质上.所以在本次分享课开课之 ...
- Asp.net core使用IIS在windows上进行托管
摘要 最近项目中,尝试使用asp.net core开发,在部署的时候,考虑现有硬件,只能部署在windows上,linux服务器暂时没有. 部署注意事项 代码中启用iis和Kestrel public ...
- ASP.NET MVC中检测浏览器版本并提示下载更新
如果网站使用html5.css3.自适应等新特性,可能有些浏览器版本不支持.这时候,需要提醒浏览者更新浏览器的版本到最新. 本篇用到的插件为:http://jreject.turnwheel.com/ ...
- 培养iOS开发新人的一个思路
坚持两个方法论: 1.发现问题的方法:(熟悉代码的过程) (1)照着一个完整的工程,从最基本的页面开始做起.不懂的地方就问,就查. (2)在阅读代码或拿到需求后要学会对问题进行分解.一个陌生的问题如果 ...
- 【CentOS】centos如何修改你的主机名
转载地址:https://www.linuxidc.com/Linux/2014-11/109238.htm ============================================= ...
- Linux进程ID号--Linux进程的管理与调度(三)
转自:http://blog.csdn.net/gatieme/article/category/6225543 日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 Linux- ...
- 用jquery实现的QQ邮箱里的多收件人选取及其他效果改进版
我们先来看一下之前网上的版本效果: 发现很多bug且应用场景不一样,没办法只能自己写了 操作时 textarea 的值只是显示效果,实现的参数为 hidden 2017-04-25再次改进版与新版的 ...
- 绝望的主妇第八季/Desperate Housewives迅雷下载
绝望的主妇 第七季 Desperate Housewives Season 8(2011) 本季看点:曾经在<主妇>中有过重要演出的达娜·德拉尼(Dana Delany), 凯尔·麦克拉克 ...
- 关于GreenPlum的一些整理
Greenplum数据库架构 Greenplum数据库基本由PostgreSQL核心增强数据库实例组合并衔接成的数据库管理系统,即Greenplum数据在PostgreSQL基础上扩展开发,每个Gre ...