我有那个班级
public class MyItem
{
public Order OrderItem { get; set; }
public string Status { get; set; }
}
Status
媒体资源可以包含值Error
,Pending
,Success
我想根据List<MyItem>()
属性对Status
对象进行排序。
我知道我可以将Status
属性的类型从string
替换为int
,然后代替Error
,Pending
,{{1我可以拥有Success
,1
,2
,然后排序操作很简单。但是我想知道如果我们必须基于3
类型属性进行排序,该怎么做。
可能的顺序:
string
,Error
,Pending
或Success
,Success
,Pending
如何使用LINQ做到这一点?
答案 0 :(得分:5)
我会使用enum
代替默认情况下每个状态为整数值,例如
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
您可以非常轻松地将现有字符串转换为enum
:
var status = (Status)Enum.Parse(typeof(Status), statusString);
答案 1 :(得分:4)
最好解析为enum
但是,你可以制作自定义比较器,
var customComparer = Comparer<string>.Create((x, y) =>
{
...
});
您可以通过函数将比较器传递给排序和顺序,例如
var sortedList = myList.OrderBy(x => x.Status, customComparer);
答案 2 :(得分:3)
最简单的方法可能是实现IComparable<T>
接口。在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);
}
}
}
答案 3 :(得分:2)
您可以定义反映所需排序的字典
Dictionary<string, int> ordering = new Dictionary<string, int> {
{ "Error", 1 },
{ "Pending", 2 },
...
}
var sortedList = myList.OrderBy(x => ordering[x.Status]);
答案 4 :(得分:1)
我认为最好更改Status的类型并用枚举替换String。然后,您可以通过为枚举的不同成员分配值来选择所需的顺序,或者根据订单方法直接订购此成员,并保留可读属性。
答案 5 :(得分:1)
由于订单按字母顺序排列,您可以做一个简单的
var result = myList.OrderBy(item => item.Status);
或
var result = myList.OrderByDescending(item => item.Status);
但是,如果您将“成功”重命名为“完成”,那么它将会中断,在这种情况下,我会推荐一个建议的enum
个答案。
答案 6 :(得分:0)
我会选择Enum选项,但鉴于它不是您首选的选项,您可以尝试以下方法:
您可以在班级中实施 IComparable<MyItem>
MyItem
在那里根据Status属性实现您的订购逻辑。如果两个状态相同,您甚至可以通过OrderItem订购,如果这适合您。
如果您需要一个例子,请随时说出
答案 7 :(得分:0)
您可以传递.OrderBy()方法,使用这样的开关对字符串进行加权:
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);
}
}