18

我需要一个关于如何使用IComparable界面的基本示例,以便我可以按升序或降序以及我正在排序的对象类型的不同字段进行排序。

4

6 回答 6

14

好吧,由于您正在使用List<T>它,因此仅使用 a 会简单得多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>(用于就地重新排序);这是一个允许Sort使用List<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)));
    }
}
于 2009-01-12T13:47:57.763 回答
12

这是一个简单的例子:

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());
    }
}
于 2009-01-12T13:34:12.033 回答
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 类的“排序”方法:

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 ) );
于 2009-01-12T13:47:39.307 回答
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();
        }
    }
}
于 2017-02-10T05:32:39.003 回答
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)
}
于 2009-01-12T14:25:48.187 回答
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);
        }
    }
于 2015-06-20T18:11:14.470 回答