• 自定义类型数组排序的两种实现方式


    Array类是C#中所有自定义类型数组的抽象类。这种自定义类型数组可以像String类型一样进行排序。这种排序的方法C#在基础类库中已经实现了,并且向外提供了可用的接口。只要按照C#中提供的方法就可以方便地实现自定义数组的排序。

    方式一:

    自定义类Person如下,想实现先按FirstName排序,再按LastName排序。如果Person类的代码可以修改的话,只要让Person类继承IComparable接口或IComparable<T>接口。该接口只提供了一个方法CompareTo(T),用这个方法返回一个Int值用以说明比较对象的大小。方法内的代码就是自定义的排序规则。

    class Person
        {
            // 属性创建快捷键 Ctr+R,E
            private string firstName;
            private string lastName;
    
            public string FirstName
            {
                get { return firstName; }
                set { firstName = value; }
            }
    
            public string LastName
            {
                get { return lastName; }
                set { lastName = value; }
            }
           
            public override string ToString()
            {
                return firstName + " " + lastName;
            }
        }

    本例的自定义规则是先按FirstName排序,再按LastName排序,代码如下:

    class Person : IComparable<Person>
        {
            private string firstName;
            private string lastName;
    
            public string FirstName
            {
                get { return firstName; }
                set { firstName = value; }
            }
    
            public string LastName
            {
                get { return lastName; }
                set { lastName = value; }
            }
            // IComparable<>接口实现
            public int CompareTo(Person other)
            {
                if (other == null) throw new ArgumentNullException("other");
    
                int result = String.Compare(firstName, other.firstName);
                if (result == 0)
                {
                    result = String.Compare(lastName, other.lastName);
                }
                return result;
            }
    
            public override string ToString()
            {
                return firstName + " " + lastName;
            }
        }

    方式二:

    有时已定义的类的代码允许修改或根本没有源代码只有DLL的时候,另一种方法就可以用了。这种方法是创建另一个自定义的继承IComparer接口或IComparer<T>接口的类,用来辅助自定义类的排序。该接口只提供了方法Compare(x,y)。(类似CompareTo(T)) 用这个方法返回一个Int值用以说明比较对象的大小。方法内的代码就是自定义的排序规则。。在辅助类PersonCompare中排序的规则定义了两条,一是先按LastName排序,再按FirstName排序,二是先按FirstName排序,再按LastName排序。并用了一个Enum枚举类来区分这两种排序。代码如下:

    enum PersonCompareType
        {
            FirstName,
            LastName
        }
    
        class PersonCompare : IComparer<Person>
        {
            private PersonCompareType compareType;
    
            public PersonCompare(PersonCompareType compareType)
            {
                this.compareType = compareType;
            }
            // IComparer<>接口实现
            public int Compare(Person x, Person y)
            {
                if (x == null) throw new ArgumentNullException("X");
                if (y == null) throw new ArgumentNullException("Y");
                int result = 0;
                switch (compareType)
                {
                    // 先按LastName排序
                    case PersonCompareType.LastName:
                        {
                            result = x.LastName.CompareTo(y.LastName);
                            if (result == 0)
                            {
                                result = x.FirstName.CompareTo(y.FirstName);
                            }
                        }
                        break;
                    // 先按FirstName排序
                    case PersonCompareType.FirstName:
                        {
                            result = x.FirstName.CompareTo(y.FirstName);
                            if (result == 0)
                            {
                                result = x.LastName.CompareTo(y.LastName);
                            }
                        }
                        break;
                    default:
                        {
                            throw new ArgumentException("unexpected compare type");
                        }
                }
                return result;
            }
        }

    两种方式的使用如下:

     static void Main(string[] args)
            {
                Person[] ps = { new Person { FirstName = "A", LastName = "C" },
                               new Person { FirstName = "C", LastName = "D" },
                               new Person { FirstName = "B", LastName = "A" }
                             };
                Console.WriteLine("FirstName");
                // 方式一 (先按FirstName排序)
                Array.Sort(ps);
                foreach (Person p in ps)
                {
                    Console.WriteLine("{0}", p.ToString());
                }
                Console.WriteLine("LastName");
                // 方式二 (先按LastName排序)
                Array.Sort(ps, new PersonCompare(PersonCompareType.LastName));
                foreach (Person p in ps)
                {
                    Console.WriteLine("{0}", p.ToString());
                }
                Console.WriteLine("FirstName");
                // 方式二 (先按FirstName排序)
                Array.Sort(ps, new PersonCompare(PersonCompareType.FirstName));
                foreach (Person p in ps)
                {
                    Console.WriteLine("{0}", p.ToString());
                }
                Console.ReadKey();
            }

    使用Array类的两个Sort方法分别与上述两种方式相结合实现排序。方式一与只有自定义数组本身的Sort方法联合使用。方式二与有自定义数组和IComparer类型两个参数的Sort方法一起使用。其实自己只需要实现排序规则说明的方法。而具体用什么方法排序是由C#基础类库实现的(当然我们也可以根据需求自己实现)。C#基础类库中用的排序方法是QuickSort算法,有机会看看源代码。

    结果如下:

    参考:C# 高级编程(第7版)

  • 相关阅读:
    api
    git分支合并
    Zookeeper 入门,看这篇就够了
    SQL分组查询
    [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:lovemu' did not find a matching property.
    事务 事务隔离级别
    DDL DML DCL的理解
    局域网和广域网
    三种数据交换方式
    通信子网和资源子网
  • 原文地址:https://www.cnblogs.com/niaomingjian/p/3523192.html
Copyright © 2020-2023  润新知