代码之家  ›  专栏  ›  技术社区  ›  Spencer Ruport

如何使用IComparable接口?

  •  17
  • Spencer Ruport  · 技术社区  · 15 年前

    我需要一个如何使用 IComparable 接口,以便我可以按升序或降序以及我正在排序的对象类型的不同字段进行排序。

    6 回复  |  直到 11 年前
        1
  •  14
  •   Marc Gravell    15 年前

    既然你在用 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);
    

    (用于就地重新订购)非常容易;下面是一个允许 Sort 列表<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)));
        }
    }
    
        2
  •  12
  •   Spencer Ruport    15 年前

    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());
        }
    }
    
        3
  •  4
  •   TcKs    15 年前

    如果需要动态排序,可以使用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 ) );
    
        4
  •  1
  •   Ghanshyam Kumar    7 年前

    您可以使用它对列表进行排序

    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();
            }
        }
    }
    
        5
  •  0
  •   peSHIr    15 年前

    这可能与排序顺序无关,但我认为它仍然是 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); }
    

    这些简单的扩展方法允许您对实现的任何类型执行参数范围检查 不可比 这样地:

    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)
    }
    
        6
  •  0
  •   Gagan    9 年前
    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);
            }
        }
    
    推荐文章