C# C排序自定义类列表
我有那门课C# C排序自定义类列表,c#,sorting,C#,Sorting,我有那门课 public class MyItem { public Order OrderItem { get; set; } public string Status { get; set; } } Status属性可以有值Error、Pending和Success 我想根据Status属性对列表对象进行排序 我知道我可以将Status属性的类型从string替换为int,然后将Error、Pending、Success值替换为1、2、3,这样排序操作就简单了。但是我想知道
public class MyItem
{
public Order OrderItem { get; set; }
public string Status { get; set; }
}
Status属性可以有值Error、Pending和Success
我想根据Status属性对列表对象进行排序
我知道我可以将Status属性的类型从string替换为int,然后将Error、Pending、Success值替换为1、2、3,这样排序操作就简单了。但是我想知道如果我们必须基于string-type属性进行排序,该怎么做
可能的顺序:
错误,挂起,成功或成功,挂起,错误
如何使用LINQ实现这一点?我将使用枚举,默认情况下,枚举为每个状态提供一个整数值,例如
public enum Status
{
Success,
Pending,
Error
}
var sortedList = myList.OrderBy(x => x.Status);
// sort by Success, Pending and then Error
var sortedList = myList.OrderByDescending(x => x.Status);
// sort by Error, Pending, Success
您可以非常轻松地将现有字符串转换为枚举:
var status = (Status)Enum.Parse(typeof(Status), statusString);
我认为最好更改状态的类型并用枚举替换字符串。然后,您可以通过将值分配给枚举的不同成员来选择所需的顺序,或者根据您的顺序方法直接对该成员进行排序,并保留可读属性。最简单的方法可能是实现IComparable接口。在MyItem类上实现此接口将确保在对MyItem实例列表排序时,将使用CompareTo方法中指定的排序。对于您的用例,这将产生如下代码:
public class MyItem : IComparable<MyItem>
{
public string OrderItem { get; set; }
public string Status { get; set; }
public int CompareTo(MyItem other)
{
if (other == null)
{
return 1;
}
if (other.Status == this.Status)
{
return 0;
}
var statusAsInt = this.Status == "Error" ? 0 : (this.Status == "Pending" ? 1 : 2);
var otherStatusAsInt = other.Status == "Error" ? 0 : (other.Status == "Pending" ? 1 : 2);
if (statusAsInt == otherStatusAsInt)
{
return 0;
}
return statusAsInt < otherStatusAsInt ? -1 : 1;
}
}
internal class Program
{
private static void Main(string[] args)
{
var myItems = new List<MyItem> { new MyItem { Status = "Pending" }, new MyItem { Status = "Error" }, new MyItem { Status = "Success " } };
myItems.Sort();
foreach (var myItem in myItems)
{
Console.WriteLine(myItem.Status);
}
}
}
List<MyItem> lst = new List<MyItem>();
lst.Add(new MyItem() { Status = "Pending" });
lst.Add(new MyItem() { Status = "Error" });
lst.Add(new MyItem() { Status = "Invalid String" });
lst.Add(new MyItem() { Status = "Success" });
var ascList =
lst.OrderBy((x) => { switch (x.Status) { case "Error": return 0; case "Pending": return 1; case "Success": return 3; default: return 4; } });
var descList =
lst.OrderByDescending((x) => { switch (x.Status) { case "Error": return 0; case "Pending": return 1; case "Success": return 3; default: return 4; } });
Console.WriteLine("Asc\n===");
foreach (MyItem mi in ascList)
{
Console.WriteLine(mi.Status);
}
Console.WriteLine("\nDesc\n====");
foreach (MyItem mi in descList)
{
Console.WriteLine(mi.Status);
}
}
由于顺序恰好是按字母顺序排列的,所以您可以执行一个简单的操作
var result = myList.OrderBy(item => item.Status);
或
但是,如果您将Success重命名为Complete,那么它将中断,在这种情况下,我建议您选择一个建议的枚举答案。您可以定义一个反映所需顺序的字典
Dictionary<string, int> ordering = new Dictionary<string, int> {
{ "Error", 1 },
{ "Pending", 2 },
...
}
var sortedList = myList.OrderBy(x => ordering[x.Status]);
解析为枚举更好,但是,您可以制作一个自定义比较器
var customComparer = Comparer<string>.Create((x, y) =>
{
...
});
我会选择Enum选项,但鉴于它不是您的首选选项,您可以尝试以下方法: 可以在类MyItem中实现IComparable 在那里,根据Status属性实现您的排序逻辑。如果两种状态相等,您甚至可以按OrderItem进行订购,如果这适合您的话
如果您需要一个示例,请随意这样说,您可以通过使用如下开关对字符串进行加权的方法传递.order:
public class MyItem : IComparable<MyItem>
{
public string OrderItem { get; set; }
public string Status { get; set; }
public int CompareTo(MyItem other)
{
if (other == null)
{
return 1;
}
if (other.Status == this.Status)
{
return 0;
}
var statusAsInt = this.Status == "Error" ? 0 : (this.Status == "Pending" ? 1 : 2);
var otherStatusAsInt = other.Status == "Error" ? 0 : (other.Status == "Pending" ? 1 : 2);
if (statusAsInt == otherStatusAsInt)
{
return 0;
}
return statusAsInt < otherStatusAsInt ? -1 : 1;
}
}
internal class Program
{
private static void Main(string[] args)
{
var myItems = new List<MyItem> { new MyItem { Status = "Pending" }, new MyItem { Status = "Error" }, new MyItem { Status = "Success " } };
myItems.Sort();
foreach (var myItem in myItems)
{
Console.WriteLine(myItem.Status);
}
}
}
List<MyItem> lst = new List<MyItem>();
lst.Add(new MyItem() { Status = "Pending" });
lst.Add(new MyItem() { Status = "Error" });
lst.Add(new MyItem() { Status = "Invalid String" });
lst.Add(new MyItem() { Status = "Success" });
var ascList =
lst.OrderBy((x) => { switch (x.Status) { case "Error": return 0; case "Pending": return 1; case "Success": return 3; default: return 4; } });
var descList =
lst.OrderByDescending((x) => { switch (x.Status) { case "Error": return 0; case "Pending": return 1; case "Success": return 3; default: return 4; } });
Console.WriteLine("Asc\n===");
foreach (MyItem mi in ascList)
{
Console.WriteLine(mi.Status);
}
Console.WriteLine("\nDesc\n====");
foreach (MyItem mi in descList)
{
Console.WriteLine(mi.Status);
}
}
为什么是字符串而不是枚举?你可以编写一个自定义的IComparer,但是,就像@PLB所说的,为什么不使用枚举呢?我已经这样做了,但是我想知道字符串case@Tony如果必须比较字符串,则需要编写自己的IComparer类或使MyItem类实现IComparable。然而,我肯定会推动切换到枚举在这种情况下,这是正确的方式去做。