如何使用IComparable和IComparer对对象列表进行排序

时间:2014-11-11 15:38:41

标签: c# list sorting icomparable icomparer

我试图实现此链接的相同示例,但更多地依赖于依赖孩子的数量。

http://www.codeproject.com/Articles/42839/Sorting-Lists-using-IComparable-and-IComparer-Inte

所以我有3名员工,分别为A:0,B:0,C:2。我想按照孩子的数量对他们进行贬低。所以我会得到C:2,B:0,A:0

但是我的名单没有排序。它保持为A:0,B:0,C:2

我做错了什么?

我的比较

public class EmployeeComparer : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        this.CompareNumberOfKids(x, y);
    }

    public int CompareNumberOfKids(Employee x, Employee y)
    {
        if (x.NumberOfKids > y.NumberOfKids)
        {
            return -1;
        }
        else if (x.NumberOfKids < y.NumberOfKids)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

我的商家实体

public class Employee : IComparable<Employee>
{
    //...//
    Public NumberOfKids { get; set; }

    int IComparable<Employee>.CompareTo(Employee next)
    {
        return new EmployeeComparer().Compare(this, next);
    }

    public override bool Equals(object obj)
    {
        if (obj != null && obj is Emmployee)
        {
            return ((Employee)obj).ID.Equals(this.ID);
        }
        else return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

Aspx.cs

public List<Employee> GetEmployeeSortedList()
{
    List<Employee> list = new List<Employee>();
    list.Add(new Employee() { Name = "A", NumberOfKids = 0 } );
    list.Add(new Employee() { Name = "B", NumberOfKids = 0 } );
    list.Add(new Employee() { Name = "C", NumberOfKids = 2 } );
    list.Add(new Employee() { Name = "D", NumberOfKids = 1 } );
    list.Add(new Employee() { Name = "E", NumberOfKids = 0 } );
    list.Add(new Employee() { Name = "F", NumberOfKids = 4 } );

    list = list.Take(3).ToList();
    EmployeeComparer comp = new EmployeeComparer();
    list.Sort(comp);
    return list;
}

2 个答案:

答案 0 :(得分:5)

首先,如果您的IComparer<Employee>类使用相同的排序条件实现Employee,则不需要通过降序排序IComparable<Employee>。对于Employee类来说,为每个比较实例化一个新的IComparer<Employee>是非常低效的。

您应该更改Employee课程,使其CompareTo看起来像这样:

int CompareTo(Employee next)
{
    return next.NumberOfKids.CompareTo(this.NumberOfKids);
}

然后你可以完全抛弃EmployeeComparer并按照这样排序:

list = list.Take(3).ToList();
list.Sort();  // Uses default IComparable for the Employee class
return list;

通常,您使类上的IComparable<T>实现执行默认排序顺序。对于员工而言,这可能是员工ID或姓氏,名字。 IComparer<T>实现应该用于其他排序标准。

但是,使用List<T>,您还有另一种选择:使用匿名函数。例如,您可以通过编写:

来完成此操作
list.Sort((x, y) => y.NumberOfKids.CompareTo(x.NumberOfKids));

请参阅this List.Sort overload

或者,您可以完全抛弃IComparer<T>IComparable<T>以及List.Sort的全部想法,并以LINQ方式执行:

var result = list.Take(3).OrderByDescending(x => x.NumberOfKids).ToList();

答案 1 :(得分:0)

这是从msdn那里获得的另一种方法

using System;
using System.Collections;
namespace ConsoleEnum
{   
   public class car : IComparable
   {      
      // Beginning of nested classes.

      // Nested class to do ascending sort on year property.
      private class sortYearAscendingHelper: IComparer
      {
         int IComparer.Compare(object a, object b)
         {
            car c1=(car)a;
            car c2=(car)b;

            if (c1.year > c2.year)
               return 1;

            if (c1.year < c2.year)
               return -1;

            else
               return 0;
         }
      }

      // Nested class to do descending sort on year property.
      private class sortYearDescendingHelper: IComparer
      {
         int IComparer.Compare(object a, object b)
         {
            car c1=(car)a;
            car c2=(car)b;

            if (c1.year < c2.year)
               return 1;

            if (c1.year > c2.year)
               return -1;

            else
               return 0;
         }
      }

      // Nested class to do descending sort on make property.
      private class sortMakeDescendingHelper: IComparer
      {
         int IComparer.Compare(object a, object b)
         {
            car c1=(car)a;
            car c2=(car)b;
             return String.Compare(c2.make,c1.make);
         }
      }

      // End of nested classes.

      private int year;
      private string make;

      public car(string Make,int Year)
      {
         make=Make;
         year=Year;
      }

      public int Year
      {
         get  {return year;}
         set {year=value;}
      }

      public string Make
      {
         get {return make;}
         set {make=value;}
      }

      // Implement IComparable CompareTo to provide default sort order.
      int IComparable.CompareTo(object obj)
      {
         car c=(car)obj;
         return String.Compare(this.make,c.make);
      }

      // Method to return IComparer object for sort helper.
      public static IComparer sortYearAscending()
      {      
         return (IComparer) new sortYearAscendingHelper();
      }

      // Method to return IComparer object for sort helper.
      public static IComparer sortYearDescending()
      {      
         return (IComparer) new sortYearDescendingHelper();
      }

      // Method to return IComparer object for sort helper.
      public static IComparer sortMakeDescending()
      {      
        return (IComparer) new sortMakeDescendingHelper();
      }

   }
}

这是使用方法

using System;

namespace ConsoleEnum
{
   class host
   {
      [STAThread]
      static void Main(string[] args)
      {
         // Create an arary of car objects.      
         car[] arrayOfCars= new car[6]
         {
            new car("Ford",1992),
            new car("Fiat",1988),
            new car("Buick",1932),
            new car("Ford",1932),
            new car("Dodge",1999),
            new car("Honda",1977)
         };

         // Write out a header for the output.
         Console.WriteLine("Array - Unsorted\n");

         foreach(car c in arrayOfCars)
            Console.WriteLine(c.Make + "\t\t" + c.Year);

         // Demo IComparable by sorting array with "default" sort order.
         Array.Sort(arrayOfCars);
         Console.WriteLine("\nArray - Sorted by Make (Ascending - IComparable)\n");

         foreach(car c in arrayOfCars)
            Console.WriteLine(c.Make + "\t\t" + c.Year);

         // Demo ascending sort of numeric value with IComparer.
         Array.Sort(arrayOfCars,car.sortYearAscending());
         Console.WriteLine("\nArray - Sorted by Year (Ascending - IComparer)\n");

         foreach(car c in arrayOfCars)
            Console.WriteLine(c.Make + "\t\t" + c.Year);

         // Demo descending sort of string value with IComparer.
         Array.Sort(arrayOfCars,car.sortMakeDescending());
         Console.WriteLine("\nArray - Sorted by Make (Descending - IComparer)\n");

         foreach(car c in arrayOfCars)
            Console.WriteLine(c.Make + "\t\t" + c.Year);

         // Demo descending sort of numeric value using IComparer.
         Array.Sort(arrayOfCars,car.sortYearDescending());
         Console.WriteLine("\nArray - Sorted by Year (Descending - IComparer)\n");

         foreach(car c in arrayOfCars)
            Console.WriteLine(c.Make + "\t\t" + c.Year);

         Console.ReadLine();
      }
   }
}