2009-01-12 37 views

回答

14

好吧,既然你使用的是List<T>這將是僅使用Comparison<T>就簡單多了,例如:

List<Foo> data = ... 
// sort by name descending 
data.Sort((x,y) => -x.Name.CompareTo(y.Name)); 

當然,與LINQ你可以只使用:

var ordered = data.OrderByDescending(x=>x.Name); 

List<T>你可以重新引入這個(就地重新排序)很容易;下面是允許SortList<T>與lambda語法的例子:

using System; 
using System.Collections.Generic; 

class Foo { // formatted for vertical space 
    public string Bar{get;set;} 
} 
static class Program { 
    static void Main() { 
     List<Foo> data = new List<Foo> { 
      new Foo {Bar = "abc"}, new Foo {Bar = "jkl"}, 
      new Foo {Bar = "def"}, new Foo {Bar = "ghi"} 
     }; 
     data.SortDescending(x => x.Bar); 
     foreach (var row in data) { 
      Console.WriteLine(row.Bar); 
     } 
    } 

    static void Sort<TSource, TValue>(this List<TSource> source, 
      Func<TSource, TValue> selector) { 
     var comparer = Comparer<TValue>.Default; 
     source.Sort((x,y)=>comparer.Compare(selector(x),selector(y))); 
    } 
    static void SortDescending<TSource, TValue>(this List<TSource> source, 
      Func<TSource, TValue> selector) { 
     var comparer = Comparer<TValue>.Default; 
     source.Sort((x,y)=>comparer.Compare(selector(y),selector(x))); 
    } 
} 
9

這裏有一個簡單的例子:「這是偉大的,但如果我希望能夠通過另一個字段來控制排序順序,或排序什麼」

public class SortableItem : IComparable<SortableItem> 
{ 
    public int someNumber; 

    #region IComparable<SortableItem> Members 

    public int CompareTo(SortableItem other) 
    { 
     int ret = -1; 
     if (someNumber < other.someNumber) 
      ret = -1; 
     else if (someNumber > other.someNumber) 
      ret = 1; 
     else if (someNumber == other.someNumber) 
      ret = 0; 
     return ret; 
    } 

    #endregion 
} 

簡單。我們所需要做的就是爲對象添加更多的字段。首先,我們將爲不同的排序類型添加一個字符串,然後添加一個布爾值來表示我們是按降序還是按升序排序,然後添加一個字段來確定我們要搜索哪個字段。

public class SortableItem : IComparable<SortableItem> 
{ 
    public enum SortFieldType { SortNumber, SortString } 

    public int someNumber = -1; 
    public string someString = ""; 
    public bool descending = true;  
    public SortFieldType sortField = SortableItem.SortFieldType.SortNumber;   

    #region IComparable<SortableItem> Members 

    public int CompareTo(SortableItem other) 
    { 
     int ret = -1; 
     if(sortField == SortableItem.SortFieldType.SortString) 
     { 
      // A lot of other objects implement IComparable as well. 
      // Take advantage of this. 
      ret = someString.CompareTo(other.someString); 
     } 
     else 
     { 
      if (someNumber < other.someNumber) 
       ret = -1; 
      else if (someNumber > other.someNumber) 
       ret = 1; 
      else if (someNumber == other.someNumber) 
       ret = 0; 
     } 
     // A quick way to switch sort order: 
     // -1 becomes 1, 1 becomes -1, 0 stays the same. 
     if(!descending) ret = ret * -1; 

     return ret; 
    } 

    #endregion 

    public override string ToString() 
    { 
     if(sortField == SortableItem.SortFieldType.SortString) 
      return someString; 
     else 
      return someNumber.ToString(); 
    } 
} 

「告訴我怎麼做!」

好,因爲你問得很好。

static class Program 
{ 
    static void Main() 
    { 

     List<SortableItem> items = new List<SortableItem>(); 
     SortableItem temp = new SortableItem(); 
     temp.someString = "Hello"; 
     temp.someNumber = 1; 
     items.Add(temp); 
     temp = new SortableItem(); 
     temp.someString = "World"; 
     temp.someNumber = 2; 
     items.Add(temp); 
     SortByString(items); 
     Output(items); 
     SortAscending(items); 
     Output(items); 
     SortByNumber(items); 
     Output(items); 
     SortDescending(items); 
     Output(items); 
     Console.ReadKey(); 
    } 

    public static void SortDescending(List<SortableItem> items) 
    { 
     foreach (SortableItem item in items) 
      item.descending = true; 
    } 
    public static void SortAscending(List<SortableItem> items) 
    { 
     foreach (SortableItem item in items) 
      item.descending = false; 
    } 
    public static void SortByNumber(List<SortableItem> items) 
    { 
     foreach (SortableItem item in items) 
      item.sortField = SortableItem.SortFieldType.SortNumber; 
    } 
    public static void SortByString(List<SortableItem> items) 
    { 
     foreach (SortableItem item in items) 
      item.sortField = SortableItem.SortFieldType.SortString; 
    } 
    public static void Output(List<SortableItem> items) 
    { 
     items.Sort(); 
     for (int i = 0; i < items.Count; i++) 
      Console.WriteLine("Item " + i + ": " + items[i].ToString()); 
    } 
} 
+0

這實際上是相當yeucky,遺憾地說。有更好的方法,特別是使用LINQ或LINQ啓發式的方法...... – 2009-01-12 13:44:15

+5

如果你有更好的主意,沒有任何說你不能回答這個問題。 – 2009-01-12 13:45:37

+0

我有 - 我只是寫它; -p – 2009-01-12 13:49:25

4

如果你想動態排序,你可以使用LINQ

var itemsOrderedByNumber = (from item in GetClasses() orderby item.Number select item).ToList(); 
var itemsOrderedByText = (from item in GetClasses() orderby item.Text select item).ToList(); 
var itemsOrderedByDate = (from item in GetClasses() orderby item.Date select item).ToList(); 

或 「分類」 列表類的方法:

List<Class1> itemsOrderedByNumber2 = new List<Class1>(GetClasses()); 
itemsOrderedByNumber2.Sort((a, b) => Comparer<int>.Default.Compare(a.Number, b.Number)); 

List<Class1> itemsOrderedByText2 = new List<Class1>(GetClasses()); 
itemsOrderedByText2.Sort((a, b) => Comparer<string>.Default.Compare(a.Text, b.Text)); 

List<Class1> itemsOrderedByDate2 = new List<Class1>(GetClasses()); 
itemsOrderedByDate2.Sort((a, b) => Comparer<DateTime>.Default.Compare(a.Date, b.Date)); 
0

這可能不是有關排序順序,但它仍然是 - 我認爲 - 一個有趣的使用IComparable

public static void MustBeInRange<T>(this T x, T minimum, T maximum, string paramName) 
where T : IComparable<T> 
{ 
    bool underMinimum = (x.CompareTo(minimum) < 0); 
    bool overMaximum = (x.CompareTo(maximum) > 0); 
    if (underMinimum || overMaximum) 
    { 
     string message = string.Format(
      System.Globalization.CultureInfo.InvariantCulture, 
      "Value outside of [{0},{1}] not allowed/expected", 
      minimum, maximum 
     ); 
     if (string.IsNullOrEmpty(paramName)) 
     { 
      Exception noInner = null; 
      throw new ArgumentOutOfRangeException(message, noInner); 
     } 
     else 
     { 
      throw new ArgumentOutOfRangeException(paramName, x, message); 
     } 
    } 
} 

public static void MustBeInRange<T>(this T x, T minimum, T maximum) 
where T : IComparable<T> { x.MustBeInRange(minimum, maximum, null); } 

這些簡單的擴展方法允許您執行任何類型的參數範圍檢查,如下所示執行IComparable

public void SomeMethod(int percentage, string file) { 
    percentage.MustBeInRange(0, 100, "percentage"); 
    file.MustBeInRange("file000", "file999", "file"); 
    // do something with percentage and file 
    // (caller will have gotten ArgumentOutOfRangeExceptions when applicable) 
} 
0
using System; 
using System.Collections.Generic; 
using System.Text; 

namespace Sorting_ComplexTypes 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Customer customer1 = new Customer { 
       ID = 101, 
       Name = "Mark", 
       Salary = 2400, 
       Type = "Retail Customers" 
      }; 
      Customer customer2 = new Customer 
      { 
       ID = 102, 
       Name = "Brian", 
       Salary = 5000, 
       Type = "Retail Customers" 
      }; 
      Customer customer3 = new Customer 
      { 
       ID = 103, 
       Name = "Steve", 
       Salary = 3400, 
       Type = "Retail Customers" 
      }; 

      List<Customer> customer = new List<Customer>(); 
      customer.Add(customer1); 
      customer.Add(customer2); 
      customer.Add(customer3); 

      Console.WriteLine("Before Sorting"); 
      foreach(Customer c in customer) 
      { 
       Console.WriteLine(c.Name); 
      } 

      customer.Sort(); 
      Console.WriteLine("After Sorting"); 
      foreach(Customer c in customer) 
      { 
       Console.WriteLine(c.Name); 
      } 

      customer.Reverse(); 
      Console.WriteLine("Reverse Sorting"); 
      foreach (Customer c in customer) 
      { 
       Console.WriteLine(c.Name); 
      } 
      } 
     } 
    } 
    public class Customer : IComparable<Customer> 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public int Salary { get; set; } 
     public string Type { get; set; } 

     public int CompareTo(Customer other) 
     { 
      return this.Name.CompareTo(other.Name); 
     } 
    } 
1

您可以使用此排序列表

namespace GenaricClass 
{ 
    class Employee :IComparable<Employee> 
    { 
     public string Name { get; set; } 
     public double Salary { get; set; } 

     public int CompareTo(Employee other) 
     { 
      if (this.Salary < other.Salary) return 1; 
      else if (this.Salary > other.Salary) return -1; 
      else return 0; 
     } 

     public static void Main() 
     { 
      List<Employee> empList = new List<Employee>() 
      { 
       new Employee{Name="a",Salary=140000}, 
       new Employee{Name="b",Salary=120000}, 
       new Employee{Name="c",Salary=160000}, 
       new Employee{Name="d",Salary=10000} 
      }; 
      empList.Sort(); 
      foreach (Employee emp in empList) 
      { 
       System.Console.Write(emp.Salary +","); 
      } 
      System.Console.ReadKey(); 
     } 
    } 
}