排序自定义对象列表

本文关键字:列表 对象 自定义 排序 | 更新日期: 2023-09-27 17:52:45

我有一个包含List<>的对象,它来自一个具有String属性的类,我想使用以下规则进行排序:

  1. 列表中所有"代码"为X5的对象都应该放在列表的顶部。
  2. 列表中"代码"为G2的所有对象都在X5对象之后。
  3. 列表中所有"代码"为H3的对象都在G2对象之后。
  4. 所有其他对象应在列表的末尾,按"代码"的字母顺序排序。

我尝试了一些代码,但一直抛出这个异常:

系统。无法排序,因为IComparer.Compare()方法返回不一致的结果。一个值不等于其本身,或者一个值与另一个值反复比较产生不同的结果。IComparer:"。

代码尝试:

public class myObject: IComparable<myObject>
{
   int id { get; set; }
   string name { get; set; }
   string code { get; set; }
   public myObject()
   {
   }
   public int CompareTo(myObject other)
   {
       //I don't know how to write the sort logic
   }
}

之后我想创建一个列表"myObject"并排序:

List<myObject> objects = new List<myObject>();
objects.Add(new MyObject() { id = 0, name = "JENNIFER"; code = "G2"; });
objects.Add(new MyObject() { id = 1, name = "TOM"; code = "H3"; });
objects.Add(new MyObject() { id = 2, name = "JACK"; code = "G2"; });
objects.Add(new MyObject() { id = 3, name = "SAM"; code = "X5"; });
objects.Sort();

列表将按照以下顺序排列:

山姆
  • 詹妮弗
  • 杰克
  • 汤姆
  • 排序自定义对象列表

    如果有必要实现IComparable,您可以使用上述答案。但是你可以就地完成。

    objects.OrderBy(
             o => o.code == "X5" ? 1 : o.code == "G2" ? 2 : o.code == "H3" ? 3 : 4);
    

    如果你想在组中排序(即G2),你也可以添加ThenBy

    您要做的是保持"特殊代码"到它们的相对权重的映射(确定它们之间的排序顺序)。然后,当比较对象时:

    • 如果两个代码都是"特殊的",比较结果是比较它们的权重
    • 如果只有一个是特殊的,那么拥有它的对象优先出现("is smaller")
    • 如果无特殊,则比较结果为code1.CompareTo(code2)

    这将允许您在将来非常容易地维护代码(如果您需要添加更多特殊代码或更改已经拥有的代码的权重)。

    因此,代码看起来就像这样:
    private static readonly Dictionary<string, int> weights =
    new Dictionary<string, int>()
    {
        { "X5", 1 },
        { "G2", 2 },
        { "H3", 3 }
    }
    public int CompareTo(myObject other)
    {
        var thisIsSpecial = weights.ContainsKey(this.code);
        var otherIsSpecial = weights.ContainsKey(other.code);
        if (thisIsSpecial && otherIsSpecial)
        {
            return weights[this.code] - weights [other.code];
        }
        else if (thisIsSpecial)
        {
            return -1;
        }
        else if (otherIsSpecial)
        {
            return 1;
        }
        return this.code.CompareTo(other.code);
    }
    

    当然,代码需要一些改进(没有null检查,它可能是一个好主意,有一个单独的比较器,而不是硬编码一个静态映射到对象类,属性名不应该全是小写的),但思想将始终是相同的

    按照指定的顺序将代码存储在数组中。然后可以先对数组进行排序。索引对象代码值。

    int result;
    result = Array.IndexOf(codes, this.code).CompareTo(Array.IndexOf(codes, other.code));
    if (result == 0)
    {
        result = // Compare next property.
    }
    // etc.
    return result;
    

    请注意,这不是一个完整的解决方案,而只是与优先于其他代码的代码相关。首先,您必须确保这两个代码都在数组中,并处理它们不是分开的情况。