参考资料

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: |||超大  

本文内容自定义类Array.Sort参考资料System.Array.Sort 有很多对集合的操作,比如排序,查找,克隆等等,你可以利用这个类加深对IComparer、IComparable以及泛型委托、匿名方法、Lambda 表达式的理解。

下载 Demo自定义类自定义两个类:Person和PersonComparer。后面会用到这两个类。

自定义Person类Person类有两个属性:FirstName和LastName,重构了ToString方法。该类还继承IComparable接口,实现了CompareTo方法,会在后面Array.Sort方法中用到。如下所示:

publicclassPerson : IComparable

{

publicPerson()

{

}

publicPerson(stringfirstname,stringlastname)

{

this.FirstName = firstname;

this.LastName = lastname;

}

publicstringFirstName { get; set; }

publicstringLastName { get; set; }

publicoverridestringToString()

{

returnstring.Format("{0} {1}", FirstName, LastName);

}

publicintCompareTo(objectobj)

{

Person other = objasPerson;

returnthis.LastName.CompareTo(other.LastName);

}

}

说明:CompareTo方法,它提供了默认比较,按LastName升序排序。

自定义PersonComparer 类该类内部定义了一个比较类型,可以按FirstName或LastName比较,并且都是升序排序。PersonComparer类同时继承IComparer接口的非泛型形式和泛型形式,实现了它们相应的Compare方法,该方法会在Array.Sort中用到。如下所示:

publicclassPersonComparer : IComparer, IComparer<Person>

{

publicenumPersonCompareType

{

FirstName,

LastName

}

PRivatePersonCompareType compareType;

publicPersonComparer(PersonCompareType compareType)

{

this.compareType = compareType;

}

publicintCompare(objectx,objecty)

{

Person p1 = xasPerson;

Person p2 = yasPerson;

switch(compareType)

{

casePersonCompareType.FirstName:

returnp1.FirstName.CompareTo(p2.FirstName);

casePersonCompareType.LastName:

returnp1.LastName.CompareTo(p2.LastName);

default:

thrownewArgumentException("unexpected compare type");

}

}

publicintCompare(Person x, Person y)

{

Person p1 = x;

Person p2 = y;

switch(compareType)

{

casePersonCompareType.FirstName:

returnp1.FirstName.CompareTo(p2.FirstName);

casePersonCompareType.LastName:

returnp1.LastName.CompareTo(p2.LastName);

default:

thrownewArgumentException("unexpected compare type");

}

}

}

Array.SortArray.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 = {

newPerson("Emerson","Fittipaldi"),

newPerson("Niki","Lauda"),

newPerson("Ayrton","Senna"),

newPerson("Michael","Schumacher")

};

采用Sort(Array)这个方法,按姓的升序排序,如下代码所示:

Array.Sort(persons);

因为定义Person类时,继承了IComparer接口,并实现了CompareTo方法,里面规定了按姓LastName比较,并且是升序,所以Array.Sort方法就知道如何排序了。

如果有时需要按FirstName排序,有时用LastName,怎么办?这就需要自定义的类PersonComparer。采用Sort(Array, IComparer)这个方法,代码如下所示:

Array.Sort(persons,newPersonComparer(PersonComparer.PersonCompareType.FirstName));

Console.WriteLine("Sort By First Name:");

foreach(Person pinpersons)

{

Console.WriteLine(" "+ p);

}

Array.Sort(persons,newPersonComparer(PersonComparer.PersonCompareType.LastName));

Console.WriteLine("Sort By Last Name:");

foreach(Person pinpersons)

{

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)

{

returnp1.FirstName.CompareTo(p2.FirstName);

});

Array.Sort(persons,

delegate(Person p1, Person p2)

{

returnp1.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 = {

newPerson("Emerson","Fittipaldi"),

newPerson("Niki","Lauda"),

newPerson("Ayrton","Senna"),

newPerson("Michael","Schumacher")

};

Person[] personValues = {

newPerson("Emerson","Fittipaldi"),

newPerson("Niki","Lauda"),

newPerson("Ayrton","Senna"),

newPerson("Michael","Schumacher")

};

Array.Sort<Person, Person>(personKeys, personValues);

Array.Sort<Person, Person>(personKeys, personValues,newPersonComparer(PersonComparer.PersonCompareType.FirstName));

其中,

Sort有两个参数的泛型方法,personValues会按personKeys的LastName按升序排序。这是默认的;Sort有三个参数的泛型方法,personValues会按personKeys的FirstName按升序排序。

Array中的其他方法,像BinarySearch、Find相关和indexOf相关,跟Sort用法类似,因为它们的参数大都是IComparer、IComparable以及泛型委托。

参考资料.NET Framework System.Array

下载 Demo

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航