C#IComparer教程展示了如何使用IComparer接口比较C#中的值。
与数字和拉丁字符串等简单类型不同,更复杂的类型没有内在的顺序。我们必须自己定义顺序。在C#中,我们可以为此任务使用Comparison
委托、IComparer
和IComparable
接口或LINQ。
C#IComparer接口
IComparer
接口定义了一个比较方法,值类型或类实现该方法以对其实例进行排序或排序。
此接口与List.Sort
和List.BinarySearch
方法一起使用。它提供了一种自定义集合排序顺序的方法。SortedDictionary
和SortedList
属于实现此接口的类。
Compare(T, T)
Compare
方法比较两个对象并返回一个值,指示一个对象是小于、等于还是大于另一个对象。
接口被我们无法控制的类型使用;换句话说,通过我们尚未编写的代码。如果代码是我们自己开发的,我们可以使用IComparable
接口来代替。
使用IComparer
我们有更多的灵活性;我们可以在不触及类型本身的情况下定义多个比较器或更新现有的比较器。此外,它的设计更简洁,因为我们将排序实现与类型分开。
C#IComparer示例
在下面的示例中,我们对员工列表进行排序。
var employees = new List<(string, int)> { ("John Doe", 1230), ("Adam Novak", 670), ("Robin Brown", 2300), ("Rowan Cruise", 990), ("Joe Draker", 1190), ("Janet Doe", 980), ("Lucy Smith", 980), ("Thomas Moore", 1400) }; employees.Sort(new SalaryComparer()); employees.ForEach(employee => Console.WriteLine(employee)); class SalaryComparer : IComparer<(string, int)> { public int Compare((string, int) emp1, (string, int) emp2) { return emp1.Item2.CompareTo(emp2.Item2); } }
在示例中,我们在SalaryComparer
中提供了Compare
的实现。我们创建具有值类型的对象。
public int Compare((string, int) emp1, (string, int) emp2) { return emp1.Item2.CompareTo(emp2.Item2); }
Compare
方法的实现按员工的薪水对员工进行排序。
employees.Sort(new SalaryComparer());
我们对列表进行排序。该方法在排序时考虑了已实现的Compare
方法。
$ dotnet run (Adam Novak, 670) (Janet Doe, 980) (Lucy Smith, 980) (Rowan Cruise, 990) (Joe Draker, 1190) (John Doe, 1230) (Thomas Moore, 1400) (Robin Brown, 2300)
C#IComparer示例二
在下面的示例中,我们对一组用户进行排序。
var users = new User[] { new User("Robin", "bookseller"), new User("John", "gardener"), new User("John", "writer"), new User("Janet", "teacher"), new User("Andrew", "driver"), new User("Lucy", "accountant") }; Array.Sort(users, new OccupationComparer()); foreach (var user in users) { Console.WriteLine(user); } record User(string Name, string Occupation); class OccupationComparer : IComparer<User> { public int Compare(User u1, User u2) { return u1.Occupation.CompareTo(u2.Occupation); } }
该示例按升序对用户数组进行排序。我们使用记录来创建对象。
public int Compare(User u1, User u2) { return u1.Occupation.CompareTo(u2.Occupation); }
该方法按职业排序。
Array.Sort(users, new OccupationComparer());
我们将比较器传递给Array.Sort
方法。
$ dotnet run User { Name = Lucy, Occupation = accountant } User { Name = Robin, Occupation = bookseller } User { Name = Andrew, Occupation = driver } User { Name = John, Occupation = gardener } User { Name = Janet, Occupation = teacher } User { Name = John, Occupation = writer }
C#字符串比较器
StringComparer
是一个用于比较字符串的内置比较器。它表示使用特定大小写和基于文化或顺序比较规则的字符串比较操作。
var words = new List<string> { "sky", "blue", "Church", "cup", "Adam", "also", "Bratislava", "bear", "snow", "carpet", "water", "volcano", "smell", "forest", "Earth" }; words.Sort(StringComparer.Ordinal); Console.WriteLine(string.Join(", ", words)); Console.WriteLine("---------------------"); words.Sort(StringComparer.OrdinalIgnoreCase); Console.WriteLine(string.Join(", ", words));
使用Ordinal
和OrdinalIgnoreCase
规则将单词列表与StringComparer
进行比较。
$ dotnet run Adam, Bratislava, Church, Earth, also, bear, blue, carpet, cup, forest, sky, ... --------------------- Adam, also, bear, blue, Bratislava, carpet, Church, cup, Earth, forest, sky, ...
使用IComparer的C#LINQ订单
LINQ的Order
和OrderDescending
具有将IComparer
作为参数的重载变体。
var words = new List<string> { "world", "War", "abbot", "Caesar", "castle", "sky", "den", "forest", "ocean", "water", "falcon", "owl", "rain", "Earth" }; var sorted = words.Order(StringComparer.OrdinalIgnoreCase).ToList(); sorted.ForEach(w => Console.WriteLine(w)); Console.WriteLine("-------------------------"); var sorted2 = words.OrderDescending(StringComparer.OrdinalIgnoreCase).ToList(); sorted2.ForEach(w => Console.WriteLine(w));
在程序中,我们使用Order
和OrderDescending
对单词列表进行排序。我们将StringComparer.OrdinalIgnoreCase
传递给方法。
$ dotnet run world water War sky rain owl ocean forest falcon Earth den castle Caesar abbot ------------------------- abbot Caesar castle den Earth falcon forest ocean owl rain sky War water world
C#IComparer多字段
在下面的例子中,我们通过两个字段进行比较。
var users = new List<User> { new User("Robin", "bookseller"), new User("Simon", "teacher"), new User("Arnold", "teacher"), new User("John", "gardener"), new User("Adam", "gardener"), new User("Peter", "gardener"), new User("John", "writer"), new User("Janet", "teacher"), new User("Andrew", "driver"), new User("Lucy", "accountant"), new User("Michael", "teacher") }; users.Sort(new OccupationNameReverseComparer()); foreach (var user in users) { Console.WriteLine(user); } record User(string Name, string Occupation); class OccupationNameReverseComparer: IComparer<User> { public int Compare(User u1, User u2) { int res = u1.Occupation.CompareTo(u2.Occupation); if (res == 0) { res = u2.Name.CompareTo(u1.Name); } return res; } }
我们有相同职业的用户。在这种情况下,我们会比较他们的名字。
public int Compare(User u1, User u2) { int res = u1.Occupation.CompareTo(u2.Occupation); if (res == 0) { res = u2.Name.CompareTo(u1.Name); } return res; }
首先,我们根据用户的Occupation
字段比较用户。如果它们相等,我们比较它们的Name
字段。我们比较名称的方式导致降序排序。
$ dotnet run User { Name = Lucy, Occupation = accountant } User { Name = Robin, Occupation = bookseller } User { Name = Andrew, Occupation = driver } User { Name = Peter, Occupation = gardener } User { Name = John, Occupation = gardener } User { Name = Adam, Occupation = gardener } User { Name = Simon, Occupation = teacher } User { Name = Michael, Occupation = teacher } User { Name = Janet, Occupation = teacher } User { Name = Arnold, Occupation = teacher } User { Name = John, Occupation = writer }
在这篇文章中,我们使用IComparer
接口在C#中对数据进行排序。
列出所有C#教程。