吴佳鑫的个人专栏

当日事当日毕,没有任何借口

导航

对象的比较与排序(七):对泛型列表进行排序和搜索:Comparison<T>和Predicate<T>的应用

前面说到,我们可以使用 IComparer<T> 和 IComparable<T> 接口比较两个对象,然后对该类型的对象列表排序。现在我们来介绍另两个委托可以来用排序和搜索列表

先总结一下前面的内容:

MSDN上List有如下的sort重载:

如果调用无参的sort()方法,那么要求集合中的元素要实现 System.IComparable 接口,否则此方法会抛出InvalidOperationException异常。

如果集合的元素没有实现IComparable接口,则可以调用Sort(IComparer<T>),这时我们要创建一个类实现IComparer接口作为比较器来完成排序。

或者更为简单些,不需要定义一个比较器,直接给sort方法提供一个用于"比较两对象”大小的方法即可---实现Comparison<T>委托。

可以参见另一日记:

http://www.cnblogs.com/eagle1986/archive/2012/02/07/2341719.html

 

一般情况下,给列表排序需要有一个方法来比较T类型的两个对象。要在列表中搜索,也需要一个方法来检查T类型的对象,看看它是否满足某个条件。定义这样的方法很简单,这里给出两个可以使用的泛型委托。

1. Comparision<T>  这个委托类型用于排序方法,其返回类型和参数是 int method(T object A , T objectB)

2.Predicate<T> 这个委托类型用于搜索方法,其返回类型和参数是 bool method(T targetObject).

可以定义任意个这样的方法,使用它们实现 List<T> 的搜索和排序方法。

 

 

定义一个Vector类

Vector类
public class Vector
{
public double? R = null;
public double? Theta = null;

public double? ThetaRadians
{
get
{
// Convert degrees to radians.
return (Theta * Math.PI / 180.0);
}
}

public Vector(double? r, double? theta)
{
// Normalize.
if (r < 0)
{
r = -r;
theta += 180;
}
theta = theta % 360;

// Assign fields.
R = r;
Theta = theta;
}

public static Vector operator +(Vector op1, Vector op2)
{
try
{
// Get (x, y) coordinates for new vector.
double newX = op1.R.Value * Math.Sin(op1.ThetaRadians.Value)
+ op2.R.Value * Math.Sin(op2.ThetaRadians.Value);
double newY = op1.R.Value * Math.Cos(op1.ThetaRadians.Value)
+ op2.R.Value * Math.Cos(op2.ThetaRadians.Value);

// Convert to (r, theta).
double newR = Math.Sqrt(newX * newX + newY * newY);
double newTheta = Math.Atan2(newX, newY) * 180.0 / Math.PI;

// Return result.
return new Vector(newR, newTheta);
}
catch
{
// Return "null" vector.
return new Vector(null, null);
}
}

public static Vector operator -(Vector op1)
{
return new Vector(-op1.R, op1.Theta);
}

public static Vector operator -(Vector op1, Vector op2)
{
return op1 + (-op2);
}

public override string ToString()
{
// Get string representation of coordinates.
string rString = R.HasValue ? R.ToString() : "null";
string thetaString = Theta.HasValue ? Theta.ToString() : "null";

// Return (r, theta) string.
return string.Format("({0}, {1})", rString, thetaString);
}
}

 

下面定义一个集合类 Vectors

集合类
    public class Vectors : List<Vector>
{
public Vectors()
{
}

public Vectors(IEnumerable<Vector> initialItems)
{
foreach (Vector vector in initialItems)
{
Add(vector);
}
}

public string Sum()
{
StringBuilder sb = new StringBuilder();
Vector currentPoint = new Vector(0.0, 0.0);
sb.Append("origin");
foreach (Vector vector in this)
{
sb.AppendFormat(" + {0}", vector);
currentPoint += vector;
}
sb.AppendFormat(" = {0}", currentPoint);
return sb.ToString();
}
}

 

 

 

下面就是我们要定义的用于排序和搜索的方法。

View Code
    public static class VectorDelegates
{
public static int Compare(Vector x, Vector y)
{
if (x.R > y.R)
{
return 1;
}
else if (x.R < y.R)
{
return -1;
}
return 0;
}

public static bool TopRightQuadrant(Vector target)
{
if (target.Theta >= 0.0 && target.Theta <= 90.0)
{
return true;
}
else
{
return false;
}
}
}


上面的代码,  Compare用于比较,TopRightQuadrant用于搜索。

 

下面是测试代码。

测试代码
 class Program
{
static void Main(string[] args)
{
Vectors route = new Vectors();
route.Add(new Vector(2.0, 90.0));
route.Add(new Vector(1.0, 180.0));
route.Add(new Vector(0.5, 45.0));
route.Add(new Vector(2.5, 315.0));

Console.WriteLine(route.Sum());

Comparison<Vector> sorter = new Comparison<Vector>(VectorDelegates.Compare);
route.Sort(sorter);
Console.WriteLine(route.Sum());

Predicate<Vector> searcher =
new Predicate<Vector>(VectorDelegates.TopRightQuadrant);
Vectors topRightQuadrantRoute = new Vectors(route.FindAll(searcher));
Console.WriteLine(topRightQuadrantRoute.Sum());

Console.ReadKey();
}
}



总结:

1、关于 Predicate<T> 更详细用法,参见http://www.cnblogs.com/eagle1986/archive/2012/01/19/2327351.html

2、可以参见上一个日记,可以用Lamda表达式来使代码更简洁。

 

posted on 2012-02-03 17:07  _eagle  阅读(1375)  评论(0编辑  收藏  举报