如何使用 IComparable 接口?

发布于 2024-07-11 19:56:10 字数 70 浏览 5 评论 0原文

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

I need a basic example of how to use the IComparable interface so that I can sort in ascending or descending order and by different fields of the object type I'm sorting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

等你爱我 2024-07-18 19:56:10

好吧,既然您使用的是 List,那么使用 Comparison 就会简单得多,例如:

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

当然,使用 LINQ,您可以use:

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

但是您可以很容易地在 List 中重新引入它(用于就地重新排序); 下面是一个允许使用 lambda 语法对 List 进行 Sort 的示例:

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)));
    }
}

Well, since you are using List<T> it would be a lot simpler to just use a Comparison<T>, for example:

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

Of course, with LINQ you could just use:

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

But you can re-introduce this in List<T> (for in-place re-ordering) quite easily; Here's an example that allows Sort on List<T> with lambda syntax:

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)));
    }
}
于我来说 2024-07-18 19:56:10

这是一个简单的示例:

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());
    }
}

Here's a simple example:

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
}

"That's great, but what if I want to be able to control the sort order, or sort by another field?"

Simple. All we need to do is add few more fields to the object. First we'll add a string for a different sort type and then we'll add a boolean to denote whether we're sorting in descending or ascending order and then add a field which determines which field we want to search by.

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();
    }
}

"Show me how!"

Well since you asked so nicely.

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());
    }
}
靖瑶 2024-07-18 19:56:10

如果你想要动态排序,你可以使用 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 类的“Sort”方法:

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 ) );

If you want dynamic sort, you can use 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();

or "Sort" method of List class:

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 ) );
注定孤独终老 2024-07-18 19:56:10

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

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();
        }
    }
}

You can use this for sorting list

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();
        }
    }
}
萌面超妹 2024-07-18 19:56:10

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

This might not be in relation to sorting order, but it is still - I think - an interesting use of 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); }

These simple extension methods allow you to do parameter range checking for any type that implements IComparable like this:

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)
}
绿萝 2024-07-18 19:56:10
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);
        }
    }
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);
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文