对自定义对象列表进行排序

时间:2014-03-24 23:25:54

标签: c# sorting

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

  1. 列表中的所有对象&#34; code&#34; X5应位于列表的顶部。
  2. 列表中的所有对象&#34; code&#34; G2对象之后是X5
  3. 列表中的所有对象&#34; code&#34; H3对象之后是G2
  4. 所有其他对象应位于列表的末尾,按字母顺序排列&#34;代码&#34;。
  5. 我尝试了一些代码,但不断抛出此异常:

      

    System.ArgumentException:无法排序,因为IComparer.Compare()方法返回不一致的结果。要么值不等于自身,要么重复一个值与另一个值进行比较会产生不同的结果。 IComparer:&#39;&#39;。

    代码尝试:

    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
       }
    }
    

    稍后我想创建一个&#34; myObject&#34;并对其进行排序:

    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. JENNIFER
    3. JACK
    4. TOM

3 个答案:

答案 0 :(得分:4)

如果有必要实施IComparable,您可以使用上述答案。但你可以就地做到。

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

如果您想要在群组中排序(例如G2),您也可以添加ThenBy

答案 1 :(得分:2)

您要做的是保留一张特殊代码的地图&#34;到它们的相对权重(确定它们之间的排序顺序)。然后,在比较对象时:

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

答案 2 :(得分:1)

按照指定的顺序将代码存储在数组中。然后,您可以首先对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;

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