C# 对集合进行排序

场景1:当我们对一个集合类型使用Sort方法进行排序时,默认情况下Sort方法内部会调用默认比较器,这样排序出来的结果可能并不是我们期望的;
场景2:若是让集合中的元素实现IComparable接口,我们可以达到按照自己的需求进行排序的目的,但是这种有两个不灵活的地方:
1、我们想要按照其它属性进行排序需要进行代码修改
2、集合中的元素所属类型我们可能无法对其进行修改
综上,集合排序的方式大致可以分为以下三种:
第一种:使用Comparison进行排序
第二种:针对集合元素类型写一个实现IComparer接口的类,把该类的实例传给Sort方法
第三种:使用OrderBy方法,返回IEnumerable类型
代码如下:

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

namespace SortListDemo
{
    class Product
    {
        public string Name { get; set; }
        public double Price { get; set; }

        public override string ToString()
        {
            return $"{this.Name}{this.Price}";
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            var products = new List<Product>();
            products.Add(new Product() { Name = "小米", Price = 3.58d });
            products.Add(new Product() { Name = "大米", Price = 1.58d });
            products.Add(new Product() { Name = "黑米", Price = 2.58d });
            SortByComparison(products);
            SortByIComparer(products);
            SortByLinq(products);
            Console.ReadLine();
        }

        private static void SortByComparison(List<Product> products)
        {
            //第一种使用Comparison进行排序
            products.Sort(new Comparison<Product>((x, y) =>
            {
                return x.Price.CompareTo(y.Price);
            }));
            Action<Product> print = System.Console.WriteLine;
            foreach (var item in products)
            {
                print(item);
            }
        }

        private static void SortByIComparer(List<Product> products)
        {
            //第二种使用自定义的比较器
            var comparer = new ProductSortByPriceComparer();
            products.Sort(comparer);
            Action<Product> print = System.Console.WriteLine;
            foreach (var item in products)
            {
                print(item);
            }
        }

        private static void SortByLinq(List<Product> products)
        {
            //第三种使用扩展方法Linq
            foreach (var item in products.OrderBy(x => x.Price))
            {
                Console.WriteLine(item);
            }
        }
    }

    class ProductSortByPriceComparer : IComparer<Product>
    {
        public int Compare(Product x, Product y)
        {
            return x.Price.CompareTo(y.Price);
        }
    }
}

总结:使用Sort排序会影响源集合,使用Orderby排序不会影响原集合;
我更推荐,Comparison委托的方式。
下面代码是从oxyplot图表库中看到得,它实现了一个较为通用得比较工具类ComparerHelper

using System;
using System.Collections.Generic;

public static class ComparerHelper
{
    public static IComparer<T> CreateComparer<T>(Comparison<T> comparison)
    {
        return new ComparisonComparer<T>(comparison);
    }

    private class ComparisonComparer<T> : IComparer<T>
    {
        private readonly Comparison<T> comparison;

        public ComparisonComparer(Comparison<T> comparison)
        {
            this.comparison = comparison;
        }

        public int Compare(T x, T y)
        {
            return this.comparison.Invoke(x, y);
        }
    }
}

此后你就可以这样使用:

//实现你的自定义的排序逻辑
var source = new List<int> { 1, 2, 3, 0, 4, 5, 6, 7 };
var comparer = ComparerHelper.CreateComparer<int>(
    (x, y) =>
    {
        if (x == 0)
        {
            return y == 0 ? 0 : -1;
        }

        if (y == 0)
        {
            return 1;
        }

        return y.CompareTo(x);
    });

var sorted = source.OrderBy(x => x, comparer).ToList();

//sorted :{ 0, 7, 6, 5, 4, 3, 2, 1 }
posted @ 2023-03-14 10:42  BigBosscyb  阅读(456)  评论(0)    收藏  举报