自定义列表按多个条件排序

时间:2015-09-06 17:58:54

标签: c# list sorting .net-2.0

我有一个带有字符串字段的类,我希望使用多个条件对其进行排序。

有问题的课程

class Items
{
    public string ItemType {get; set;}
    public string Code {get; set;}

    // other members elided

    public Items(string _IT, string _Cd)
    {
        ItemType = _IT;
        Code = _Cd;
    }
}

使用班级

List<Items> lstItemCol = new List<Items>();

lstItemCol.Add(new Items("EE", "12345"));
lstItemCol.Add(new Items("WW", "5881"));
lstItemCol.Add(new Items("LLL", "215458"));
lstItemCol.Add(new Items("WW", "789"));
lstItemCol.Add(new Items("EE", "582"));

我想要做的是对列表进行排序,使得项目按EE排序,然后是WW,然后是LLL

输出顺序应为:

"EE", "582"
"EE", "12345"
"WW", "5881"
"WW", "789"
"LLL", "215458"

除了向类(sortOrder)添加另一个字段并对其进行排序之外,我想不出一种优雅的方式来执行此操作:我宁愿避免这种情况,只是对ItemType进行排序?

1 个答案:

答案 0 :(得分:0)

有两种方法可以以可重用和干净的方式实现它。

  1. 在项目

  2. 上实施IComparable
  3. 创建您自己的项目比较器,并将其用作按linq排序的参数。

  4. PS:我还建议使用单数形式的类名称项目而不是复数形式的项目。项目通常指集合。

    PPS:我还使用linqpad来演示实现。

    void Main()
    {
        var lstItemCol = new List<Item>();
    
        lstItemCol.Add(new Item("EE", "12345"));
        lstItemCol.Add(new Item("WW", "5881"));
        lstItemCol.Add(new Item("LLL", "215458"));
        lstItemCol.Add(new Item("WW", "789"));
        lstItemCol.Add(new Item("EE", "582"));
    
        lstItemCol.OrderBy(ic => ic).Dump();
        lstItemCol.OrderBy(ic => ic, new ItemComparer()).Dump();
    }
    
    // Define other methods and classes here
    
    class Item : IComparable<Item>, IComparable
    {
        public string ItemType { get; set; }
        public string Code { get; set; }
    
        // other members elided
    
        public Item(string _IT, string _Cd)
        {
            ItemType = _IT;
            Code = _Cd;
        }
    
        public int CompareTo(Item other)
        {
            if (other == null) return 1;
            var result = ItemType.Length.CompareTo(other.ItemType.Length);
            if (result == 0) result = ItemType.CompareTo(other.ItemType);
            if (result == 0) result = Code.Length.CompareTo(other.Code.Length);
            if (result == 0) result = Code.CompareTo(other.Code);
            return result;
        }
        int IComparable.CompareTo(object other)
        {
            return CompareTo(other as Item);
        }
    }
    
    sealed class ItemComparer : FComparer<Item>
    {
        private static readonly Func<Item, Item, int> _comparer = (v1, v2) =>
        {
            var result = v1.ItemType.Length.CompareTo(v2.ItemType.Length);
            if (result == 0) result = v1.ItemType.CompareTo(v2.ItemType);
            if (result == 0) result = v1.Code.Length.CompareTo(v2.Code.Length);
            if (result == 0) result = v1.Code.CompareTo(v2.Code);
            return result;
        };
    
        public ItemComparer()
            :base(_comparer)
        { }
    }
    
    abstract class FComparer<T> : IComparer<T>
    {
        private readonly Func<T, T, int> _comparer;
    
        protected FComparer(Func<T, T, int> comparer)
        { _comparer = comparer; }
    
        public int Compare(T v1, T v2)
        {
            return _comparer(v1, v2);
        }
    }