zoukankan      html  css  js  c++  java
  • .NET Framework System.Array.Sort 数组类,加深对 IComparer、IComparable 以及泛型委托、匿名方法、Lambda 表达式的理解

    本文内容

    • 自定义类
    • Array.Sort
    • 参考资料

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

    下载 Demo

    自定义类


    自定义两个类:PersonPersonComparer 。后面会用到这两个类。

    自定义 Person

    Person 类有两个属性:FirstNameLastName,重构了 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  类

    该类内部定义了一个比较类型,可以按 FirstNameLastName 比较,并且都是升序排序。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 会按 personKeysLastName 按升序排序。这是默认的;
    • Sort 有三个参数的泛型方法,personValues 会按 personKeysFirstName 按升序排序。

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

    参考资料


    下载 Demo

  • 相关阅读:
    自定义WordPress文件上传路径
    PHP Warning: preg_match(): JIT compilation failed: no more memory in
    Mac下PHP7.1+Nginx安装和配置
    bootstrap modal插件弹出窗口如何限制最大高度,并且在内容过多时可以滚动显示
    Language Tool ,a plugin for TeXStudio
    平均值mean,众数mode,中值median 和 标准差stddev
    LaTeX Software & Manuals
    MAFFT多重序列比对--(附比对彩标方法)
    Markdown语法 (中文版)
    在64位系统上不能安装Matlab notebook的解决方案
  • 原文地址:https://www.cnblogs.com/liuning8023/p/4276857.html
Copyright © 2011-2022 走看看