自定义列表按多个条件排序
本文关键字:条件 排序 列表 自定义 | 更新日期: 2023-09-27 18:11:38
我有一个带有字符串字段的类,我想通过使用多个条件对其进行排序。
所讨论的类
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,然后是ll
输出顺序应为:
"EE", "582"
"EE", "12345"
"WW", "5881"
"WW", "789"
"LLL", "215458"
我想不出一种优雅的方法来做到这一点,然后向类(sortOrder
)添加另一个字段并对其进行排序:我宁愿避免这种情况,只是对ItemType进行排序?
有两种可重用且干净的方法来实现它。
-
在项目上实现IComparable
-
创建你自己的物品比较器,并使用它作为linq的排序参数
PS:我还建议使用单数形式作为类名Item而不是复数形式Items。item通常指集合。
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);
}
}