【问题标题】:Custom Sorting (IComparer on three fields)自定义排序(三个字段上的 IComparer)
【发布时间】:2010-12-21 16:29:33
【问题描述】:

我有一个包含三个字段的人员类,标题、姓名、性别,我想为其创建一个自定义排序,首先按标题排序,然后按姓名排序,然后按性别升序:

public class SortPerson : IComparer
    {
        public int Compare(object x, object y)
        {
            (…)
        }
    }

我知道如何只对一个变量进行比较: 但是我必须如何处理三个?

public class SortPerson : IComparer
        {

int IComparer.Compare(object a, object b)
   {
      Person p1=(Person)a;
      Person p2=(Person)b;
      if (p1.Title > p2.Title)
         return 1;
      if (p1.Title < p2.Title)
         return -1;
      else
         return 0;
   }
}

非常感谢,

【问题讨论】:

  • 你认为你应该怎么做?一个领域自然应该更重要,对吗?然后另一个?最后一个?所以比较第一个字段。如果该结果为 0,则比较第二个。如果该结果为 0,则比较第三个。返回结果。把它变成一种方法,你就有了一个开始。然后重构它。

标签: c# .net comparison


【解决方案1】:
//Assuming all the fields implement IComparable
int result = a.field1.CompareTo(b.field1);
if (result == 0)
  result = a.field2.CompareTo(b.field2);
if (result == 0)
  result = a.field3.CompareTo(b.field3);
return result;

【讨论】:

    【解决方案2】:

    我不知道您对比较器有什么用,但也许您可以使用“order by”LINQ 语句代替比较器,它允许按各种字段排序:

    var orderedListPersons =
        from p in listPersons
        orderby p.Title, p.Name, p.Gender
        select person;
    

    将按照您想要的方式对 listPersons 进行排序。您还可以将 LINQ OrderBy 和 ThenBy 方法用于具有不同语法的同一事物:

    var orderedlistPersons = listPersons.OrderBy(p => p.Title).ThenBy(p => p.Name).ThenBy(p => p.Gender);
    

    【讨论】:

    • IComparer 用于定义类型的顺序,然后在 linq orderby 中使用它:listPersons.OrderBy(p => p)
    【解决方案3】:

    按优先顺序一次对一个字段进行排序,如果前一个字段比较结果为 0(字段相等),则仅继续到下一个字段。有关 2 字段排序的示例,请参见以下内容。

    http://csharp.2000things.com/2010/10/30/135-implementing-icomparable-to-allow-sorting-a-custom-type/

    【讨论】:

      【解决方案4】:

      一种方法是实现这样的接口。

      public class Person : IComparer<Person>
      {
          public string Titel { get; set; }
      
          int IComparer<Person>.Compare(Person x, Person y)
          {
              if (x is null)
                  throw new ArgumentNullException(nameof(x));
              if (y is null)
                  throw new ArgumentNullException(nameof(y));
      
              return x.Titel.CompareTo(y.Titel);                      
          }
      }
      

      虽然有时您可能对您想要的排序方式有更多的控制权。当然你可以使用 linq,但是你必须在速度上列出一个垃圾分配列表,而且在实现 IComparer 接口时确实不难做到。

      查看下面的示例,您会发现可以根据需要组合任意数量的属性。

      public class Person : IComparable<Person>, IComparer<Person>
      {
          public string Titel { get; set; }
      
          public string FirstName { get; set; }
      
          public string LastName { get; set; }
      
          public DateTime? SomeOptionalValue { get; set; }
      
          int IComparer<Person>.Compare(Person x, Person y)
          {       
              return (x as IComparable).CompareTo(y);
          }
      
          int IComparable<Person>.CompareTo(Person other)
          {
              if (other is null)
                  throw new ArgumentNullException(nameof(other));
              int result = this.Titel.CompareTo(other.Titel);
      
              //chain the other properties in the order you'd like to
              //have them sorted. 
              if (result == 0)
                  result = this.FirstName.CompareTo(other.FirstName);
      
              if (result == 0)
                  result = this.LastName.CompareTo(other.LastName);
      
              //use optional values as well as call the compare implementation on a class
              if (result == 0 && SomeOptionalValue.HasValue && other.SomeOptionalValue.HasValue)
                  result = DateTime.Compare(this.SomeOptionalValue.Value, other.SomeOptionalValue.Value);
      
              return result;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-02
        • 2017-07-30
        • 2021-09-28
        • 1970-01-01
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多