对泛型列表进行排序和搜索

上一篇文章介绍了使用IComparable接口和IComparer接口比较对象,然后对该类型的对象列表进行排序,这里的区别是可以使用IComparable和IComparer泛型接口。要对List<T>排序,可以再排序的类型上实现IComparable<T>泛型接口或定义IComparer<T>泛型接口。

不过这里介绍泛型委托实现对List<T>排序。

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

Comparison<T>:这个泛型委托类型用于排序方法,返回类型和参数如下:

int method(T object1, T object2)

Predicate<T>:这个泛型委托类型用于搜索方法,返回类型和参数如下:

bool method(T object)

示例如下:

创建一个控制台程序,添加一个Vector类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CH12Ex03test
{
    public class Vector
    {
        public double? R = null;      //定义可控类型矢量模长
        public double? Theta = null;  //定义可控类型矢量角度

        public double? ThetaRadians   //定义可控类型矢量弧度
        {
            get
            {
                return (Theta * Math.PI / 180.0);
            }
        }

        public Vector(double? r, double? theta)
        {
            if (r<0)
            {
                r = -r;
                theta += 180.0;
            }
            theta %= 360;
            R = r;
            Theta = theta;
        }

        public static Vector operator +(Vector op1, Vector op2)
        {
            try
            {
                double newX = op1.R.Value * Math.Sin(op1.ThetaRadians.Value) + op2.R.Value * Math.Sin(op2.ThetaRadians.Value);
                double newY = op2.R.Value * Math.Cos(op2.ThetaRadians.Value) + op2.R.Value * Math.Cos(op2.ThetaRadians.Value);

                double newR = Math.Sqrt(newX * newX + newY * newY);
                double newTheta = Math.Atan2(newX, newY) * 180.0 / Math.PI;
                return new Vector(newR, newTheta);
            }
            catch
            {
                return new Vector(null, null);
            }

        }

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

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


    }
}
然后定义一个集合类Vectors,可以使用List<Vectors>类型,但由于要定义其他方法,因此继承List<Vectors>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CH12Ex03test
{
    public class Vectors : List<Vector>
    {
        public Vectors()
        {
        }

        public Vectors(IEnumerable<Vector> initItems)  //在测试代码中会使用List<Vector>.FindAll()方法返回List<Vector>来初始化Vectors对象,
        {                                              //因此这里要增加这个非默认构造函数
            foreach (Vector vec in initItems)
            {
                Add(vec);
            }
        }

        public StringBuilder Sum()
        {
            StringBuilder sb = new StringBuilder();
            Vector currentPt = new Vector(0.0, 0.0);
            sb.AppendFormat("({0},{1})", currentPt.R, currentPt.Theta);

            foreach(Vector vec in this)
            {
                currentPt = currentPt + vec;
                sb.AppendFormat("+({0},{1})", vec.R, vec.Theta);
            }
            sb.AppendFormat("=({0},{1})", currentPt.R, currentPt.Theta);
            return sb;
        }
    }
}
定义一个委托类型和它的分别用于排序和搜索的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CH12Ex03test
{
    public static class VectorDelegates
    {
        public static int Order(Vector vec1, Vector vec2)
        {
            if (vec1.R > vec2.R)
            {
                return 1;
            }
            else if (vec1.R < vec2.R)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }

        public static bool Search(Vector vec)
        {
            if (vec.Theta > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
测试代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CH12Ex03test
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder strResult;
                 
            Vectors vectors = new Vectors();
            vectors.Add(new Vector(3.0, 45.0));
            vectors.Add(new Vector(6.0, -60.0));
            vectors.Add(new Vector(5.0, -30.0));
            vectors.Add(new Vector(2.0, 20.0));

            Console.WriteLine("矢量相加求和");
            strResult = vectors.Sum();
            Console.WriteLine(strResult);

            Console.WriteLine("按矢量模长排序后矢量相加求和");
            Comparison<Vector> sorter = new Comparison<Vector>(VectorDelegates.Order);
            vectors.Sort(sorter);
            strResult = vectors.Sum();
            Console.WriteLine(strResult);

            Console.WriteLine("只保留角度大于0的矢量");
            Predicate<Vector> searcher = new Predicate<Vector>(VectorDelegates.Search);
            Vectors restVectors = new Vectors(vectors.FindAll(searcher));
            strResult = restVectors.Sum();
            Console.WriteLine(strResult);
            Console.ReadKey();
        }
    }
}
运行结果,可以看到首次矢量相加按照对象添加到集合类中的顺序计算矢量和,第二次矢量相加先对各矢量对象按模长进行排序再求和,最后一次是只保留角度大于0的矢量求和:






猜你喜欢

转载自blog.csdn.net/GK_2014/article/details/49033957