[英]Custom Sorting (IComparer on three fields)
I have a person class with three fields, Title, Name, Gender and I would like to create a Custom Sort for it to sort it first by Title, then by Name and then by Gender ascending:我有一个包含三个字段的 person 类,Title、Name、Gender,我想为它创建一个自定义排序,首先按 Title 排序,然后按 Name 排序,然后按 Gender 升序排序:
public class SortPerson : IComparer
{
public int Compare(object x, object y)
{
(…)
}
}
I know how to do this for only one variable to compare against: But How would I have to proceed with three?我知道如何只对一个变量进行比较:但是我将如何处理三个变量?
public class SortPerson : IComparer
{
int IComparer.Compare(object a, object b)
{
Person p1=(Person)a;
Person p2=(Person)b;
if (p1.Title > p2.Title)
return 1;
if (p1.Title < p2.Title)
return -1;
else
return 0;
}
}
Many Thanks,非常感谢,
//Assuming all the fields implement IComparable
int result = a.field1.CompareTo(b.field1);
if (result == 0)
result = a.field2.CompareTo(b.field2);
if (result == 0)
result = a.field3.CompareTo(b.field3);
return result;
I don't know what's the use you have for the comparer, but maybe you could use instead of a comparer the "order by" LINQ statement, which allows to sort by various fields: 我不知道你对比较器有什么用处,但也许你可以使用“order by”LINQ语句来代替比较器,它允许按各种字段排序:
var orderedListPersons =
from p in listPersons
orderby p.Title, p.Name, p.Gender
select person;
will order listPersons the way you want. 将以您想要的方式订购listPersons。 You can also use the LINQ OrderBy and ThenBy methods for the same thing with a different syntax:
您也可以使用不同的语法将LINQ OrderBy和ThenBy方法用于同一事物:
var orderedlistPersons = listPersons.OrderBy(p => p.Title).ThenBy(p => p.Name).ThenBy(p => p.Gender);
Sort on one field at a time, in order of precedence, only continuing to the next field if the previous field compare resulted in 0 (fields equal). 按优先顺序一次按一个字段排序,如果前一个字段比较结果为0(字段相等),则仅继续到下一个字段。 See the following for an example of a 2-field sort.
有关2字段排序的示例,请参阅以下内容。
http://csharp.2000things.com/2010/10/30/135-implementing-icomparable-to-allow-sorting-a-custom-type/ http://csharp.2000things.com/2010/10/30/135-implementing-icomparable-to-allow-sorting-a-custom-type/
One way would be to implement the interface like this. 一种方法是实现这样的界面。
public class Person : IComparer<Person>
{
public string Titel { get; set; }
int IComparer<Person>.Compare(Person x, Person y)
{
if (x is null)
throw new ArgumentNullException(nameof(x));
if (y is null)
throw new ArgumentNullException(nameof(y));
return x.Titel.CompareTo(y.Titel);
}
}
Sometimes though you might have a Little more Control ober how you'd like to sort. 有时虽然你可能有一点点控制你想要排序的方式。 Sure you can use linq however then you'd have to make a list garbage allocations loss in speed and it is really not to hard to do when implementing the IComparer interface.
当然你可以使用linq,然后你必须在列表垃圾分配速度损失,并且实现IComparer接口真的不难做到。
Have a look at the below sample and you will see that you can combine as many properties as you need. 看看下面的示例,您将看到可以根据需要组合多个属性。
public class Person : IComparable<Person>, IComparer<Person>
{
public string Titel { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? SomeOptionalValue { get; set; }
int IComparer<Person>.Compare(Person x, Person y)
{
return (x as IComparable).CompareTo(y);
}
int IComparable<Person>.CompareTo(Person other)
{
if (other is null)
throw new ArgumentNullException(nameof(other));
int result = this.Titel.CompareTo(other.Titel);
//chain the other properties in the order you'd like to
//have them sorted.
if (result == 0)
result = this.FirstName.CompareTo(other.FirstName);
if (result == 0)
result = this.LastName.CompareTo(other.LastName);
//use optional values as well as call the compare implementation on a class
if (result == 0 && SomeOptionalValue.HasValue && other.SomeOptionalValue.HasValue)
result = DateTime.Compare(this.SomeOptionalValue.Value, other.SomeOptionalValue.Value);
return result;
}
}
If repeated code gives you the ick and you're wanting code that you can write once and apply to various different classes, you can implement it in a generic extension-method way like this.如果重复的代码让您感到不适,并且您想要一次编写并应用于各种不同类的代码,您可以像这样以通用扩展方法的方式实现它。
Here's my static extension methods class:这是我的静态扩展方法类:
public static class SortabilityExtensions
{
public static int CompareTo<T>(this T a, T b, params Func<T, IComparable>[] getVals) where T : IComparable<T>
{
foreach (var getVal in getVals)
{
int comparison = getVal(a).CompareTo(getVal(b));
if (comparison != 0)
return comparison;
}
return 0;
}
}
And then to get my IComparable
implementation in my Person class as per the original post, with sorting by Title then Name then Gender , my CompareTo
can look like this:然后根据原始帖子在我的 Person 类中获取我的
IComparable
实现,按Title然后Name然后Gender排序,我的CompareTo
可以如下所示:
public int CompareTo(Person other)
{
return this.CompareTo(other, a => a.Title, a => a.Name, a => a.Gender);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.