【问题标题】:Sorting a custom object list对自定义对象列表进行排序
【发布时间】:2014-03-24 23:25:54
【问题描述】:

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

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

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

System.ArgumentException:无法排序,因为 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();

列表将按以下顺序排列:

  1. SAM
  2. 詹妮弗
  3. 杰克
  4. 汤姆

【问题讨论】:

  • 从 CompareTo 方法中粘贴您的排序逻辑
  • 那么,排序逻辑在哪里?
  • 我以前从未写过排序逻辑,而且我的第一次尝试很糟糕,所以它不会像很好地解释问题那样有帮助。

标签: c# sorting


【解决方案1】:

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

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

如果您想分组订购(即G2),您也可以添加ThenBy

【讨论】:

  • @miniBill In-place 我的意思是没有实现IComperable
  • 在排序中,in place通常意味着另一件事
【解决方案2】:

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

  • 如果两个代码都是“特殊的”,则比较结果是比较它们的权重
  • 如果只有一个是特殊的,那么拥有它的对象首先出现(“更小”)
  • 若无特殊,则比较结果为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 的检查,最好有一个单独的比较器,而不是将静态映射硬编码到对象类中,属性名称不应该全部小写)但是想法永远是一样的。

【讨论】:

  • 这将为 Jack/Jennifer 提供错误的顺序 - 在这种情况下,我相信,如果该特定部分很重要(从问题中不确定)。
  • @ReedCopsey:是的,不确定排序后的示例是否“恰好”是这样的,但规则已明确说明,此时他们没有提及姓名。
【解决方案3】:

按照您指定的顺序将您的代码存储在一个数组中。然后,您可以先对 Array.IndexOf 对象代码值进行排序。

int result;

result = Array.IndexOf(codes, this.code).CompareTo(Array.IndexOf(codes, other.code));

if (result == 0)
{
    result = // Compare next property.
}

// etc.

return result;

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

【讨论】:

    猜你喜欢
    • 2013-05-06
    • 2021-07-11
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    相关资源
    最近更新 更多