C#集合排序

一個集合能否排序,要看系統知不知道排序的規則,像內建的系統類型,int ,string,short,decimal這些,系統知道怎麼排序,而若是一個集合裏面放置的是自定義類型,好比本身定義了一個Product類型,要把它排序,系統是不知道怎麼辦的。 ide

那麼,如何告知系統排序的規則呢?有如下幾種方法: this

1:對類實現IComparable接口,示例以下:spa

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

namespace SortTeset
{
    class Product : IComparable
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }

        public static List<Product> GetSampleProduct()
        {
            return new List<Product>
             {
                 new Product{Name="Watch",Price=12345.56m},
                 new Product{Name="Knife",Price=224.50m},
                 new Product{Name="Rope",Price=12.50m},
                 new Product{Name="ETorch",Price=58.5m}
             };
        }

        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Price);
        }

        int IComparable.CompareTo(object obj)
        {
            Product temp = (Product)obj;
            return this.Name.CompareTo(temp.Name);
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Product> ProductSample = Product.GetSampleProduct();
            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }

            Console.WriteLine();

            ProductSample.Sort();

            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }
        }
    }
}
其中最主要的是這句:

   class Product :IComparablecode

跟這句:orm

    int IComparable.CompareTo(object obj)
        {
            Product temp = (Product)obj;
            return this.Name.CompareTo(temp.Name);
        } 對象

就是實現了IComparable.CompareTo()這個方法。而後就能夠直接調用 SomeProductList.Sort();方法來進行排序。排序

 

2:指定IComparer  類的對象。接口

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

namespace SortTest2
{
    class Product 
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }

        public static List<Product> GetSampleProduct()
        {
            return new List<Product>
             {
                 new Product{Name="Watch",Price=12345.56m},
                 new Product{Name="Knife",Price=224.50m},
                 new Product{Name="Rope",Price=12.50m},
                 new Product{Name="ETorch",Price=58.5m}
             };
        }

        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Price);
        }

    }
    class ProductNameComparer : IComparer<Product>
     {
         public int Compare(Product first, Product second)
         {
             return first.Name.CompareTo(second.Name);
         }
     }
    class Program
    {
        static void Main(string[] args)
        {
            List<Product> ProductSample = Product.GetSampleProduct();
            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }

            Console.WriteLine();

            ProductSample.Sort(new ProductNameComparer());

            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }
        }
    }
}

這兒咱們新定義了一個類:ProductNameComparer,這個類實現了泛型接口:IComparer<Product>,而後在ci

ProductSample.Sort(new ProductNameComparer());開發

語句中咱們提供了一個比較器對象。 

這種方法看上去不如直接實現ICompareable接口來得簡潔。

 

這種方法能夠用匿名方法進行改進:

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

namespace SortTest3
{
    class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }

        public static List<Product> GetSampleProduct()
        {
            return new List<Product>
             {
                 new Product{Name="Watch",Price=12345.56m},
                 new Product{Name="Knife",Price=224.50m},
                 new Product{Name="Rope",Price=12.50m},
                 new Product{Name="ETorch",Price=58.5m}
             };
        }

        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Price);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Product> ProductSample = Product.GetSampleProduct();
            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }

            Console.WriteLine();

            ProductSample.Sort(delegate(Product first, Product second)
             {
                 return first.Name.CompareTo(second.Name);
             });

            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }
        }
    }
}

這一次,不用定義那個類,而後使用它的方法了,而是直接填充delegate接口。 

這種方法還能夠進一步用Lambda表達式改進,以下:

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

namespace SortTest4
{
    class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }

        public static List<Product> GetSampleProduct()
        {
            return new List<Product>
             {
                 new Product{Name="Watch",Price=12345.56m},
                 new Product{Name="Knife",Price=224.50m},
                 new Product{Name="Rope",Price=12.50m},
                 new Product{Name="ETorch",Price=58.5m}
             };
        }

        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Price);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Product> ProductSample = Product.GetSampleProduct();
            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }

            Console.WriteLine();

            ProductSample.Sort((first, second) => first.Name.CompareTo(second.Name));

            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }
        }
    }
}
變態的是,還能夠進一步改進,使用擴展方法,以下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SortTest5
{
    class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }

        public static List<Product> GetSampleProduct()
        {
            return new List<Product>
             {
                 new Product{Name="Watch",Price=12345.56m},
                 new Product{Name="Knife",Price=224.50m},
                 new Product{Name="Rope",Price=12.50m},
                 new Product{Name="ETorch",Price=58.5m}
             };
        }

        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Price);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Product> ProductSample = Product.GetSampleProduct();
            foreach (Product tmp in ProductSample)
            {
                Console.WriteLine(tmp);
            }

            Console.WriteLine();

            foreach (Product tmp in ProductSample.OrderBy(p => p.Name))
            {
                Console.WriteLine(tmp);
            }
        }
    }
}

「這裏彷佛調用了一個OrderBy方法,但查閱一下MSDN,就會發現這個方法在List<Product>中根本不存在。之因此能調用它,是因爲存在一個擴展方法。這裏實際再也不是"原地"對列表進行排序,而只是按特定的順序獲取列表的內容。有的時候,你須要更改實際的列表;但有的時候,沒有任何反作用的排序顯得更"善解人意"。重點在於,如今的寫法更簡潔,可讀性更好(固然是在你理解了語法以後)。咱們的想法是"列表按名稱排序",如今的代碼正是這樣作的。並非"列表經過將一個產品的名稱與另外一個產品的名稱進行比較來排序",就像C# 2代碼所作的那樣。也不是使用知道如何將一個產品與另外一個產品進行比較的另外一個類型的實例來按名稱排序。這種簡化的表達方式是C# 3的核心優點之一。既然單獨的數據查詢和操做是如此的簡單,那麼在執行更大規模的數據處理時,仍然能夠保持代碼的簡潔性和可讀性,這進而鼓勵開發者以一種"以數據爲中心"的方式來觀察世界。」 

最後這兩步的語法,絕對是一個會用其它語言好比C/C++,VB的人所沒法明白的,C#進化速度真是快。。。。。。。


再來看看另一位大神對student類的排序

student類:

public class Student
{
    public string name;
    public int num;
    
    //下面是一些方法及屬性
    // ......
}
排序一:

List<Student> students = new List<Student>();
List<Student> sortedStudents = students.OrderBy(s => s.num).ToList();
逆序:

List<Student> sortedStudents = students.OrderByDescending(s => s.num).ToList();
排序二(Sort):

students.Sort(delegate(Student a, Student b) { return a > b; });
排序三:

List<Student> students = new List<Student>();
//Linq
List<Student> sortedStudents = students.OrderByDescending(s => s.num).ToList();
//List.Sort
students.Sort((Comparison<Student>)delegate(Student a, Student b) { return a.num > b.num ? 1 : a.num == b.num ? 0 : -1; });
//Array.Sort
Array.Sort(students.ToArray(), (Comparison<Student>)delegate(Student a, Student b) { return a.num > b.num ? 1 : a.num == b.num ? 0 : -1; });

排序四:

//ps
//Array.Sort
Array.Sort(students.ToArray(), (Comparison<Student>)delegate(Student a, Student b) { return a.num > b.num ? 1 : a.num == b.num ? 0 : -1; });

//這只是例子,實際不能這麼寫哦。須要寫
Student[] SortedArray = students.ToArray();
Array.Sort(SortedArray, (Comparison<Student>)delegate(Student a, Student b) { return a.num > b.num ? 1 : a.num == b.num ? 0 : -1; });
相關文章
相關標籤/搜索