Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C排序自定义类列表_C#_Sorting - Fatal编程技术网

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。然而,我肯定会推动切换到枚举在这种情况下,这是正确的方式去做。