C#排序自定义类列表

时间:2013-06-06 10:24:06

标签: c# sorting

我有那个班级

public class MyItem
{
    public Order OrderItem { get; set; }
    public string Status { get; set; }
}

Status媒体资源可以包含值ErrorPendingSuccess

我想根据List<MyItem>()属性对Status对象进行排序。

我知道我可以将Status属性的类型从string替换为int,然后代替ErrorPending,{{1我可以拥有Success12,然后排序操作很简单。但是我想知道如果我们必须基于3类型属性进行排序,该怎么做。

可能的顺序:

stringErrorPendingSuccessSuccessPending

如何使用LINQ做到这一点?

8 个答案:

答案 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);
     }
  }