我的问题是我总是想以某种方式订购一组对象。
例如:
class foo{
public string name {get;set;}
public DateTime date {get;set;}
public int counter {get;set;}
}
...
IEnumerable<foo> dosomething(foo[] bar){
return bar.OrderBy(a=>a.name).ThenBy(a=>a.date).ThenBy(a=>a.counter);
}
我遇到的问题是它总是很长时间地处理排序顺序。一个简洁的解决方案似乎只是创建一个实现IComparer<foo>
的类,这意味着我可以这样做:
IEnumerable<foo> dosomething(foo[] bar){
return bar.OrderBy(a=>a, new fooIComparer())
}
问题是,这个实现的订购方法如下
...
public int Compare(foo x, foo y){ }
意味着它在非常精细的基础上进行比较。
当前的实现(虽然我正在编写伪代码,但可能会有效)
public int Compare(foo x, foo y){
if (x==y)
return 0;
var order = new []{x,y}.OrderBy(a=>a.name).ThenBy(a=>a.date).ThenBy(a=>a.counter);
return (order[0] == x) ? -1 : -1;//if x is first in array it is less than y, else it is greater
}
这不是很有效,另一个可以提供更整洁的解决方案吗?理想情况下,没有比较(x,y)方法?
答案 0 :(得分:3)
当您按多种条件订购时,您将在每种情况下单独检查;例如,如果x.name
和y.name
相等,那么您需要检查x.date
和y.date
,依此类推。
public class FooComparer : IComparer<Foo>
{
public int Compare(Foo x, Foo y)
{
// nasty null checks!
if (x == null || y == null)
{
return x == y ? 0
: x == null ? -1
: 1;
}
// if the names are different, compare by name
if (!string.Equals(x.Name, y.Name))
{
return string.Compare(x.Name, y.Name);
}
// if the dates are different, compare by date
if (!DateTime.Equals(x.Date, y.Date))
{
return DateTime.Compare(x.Date, y.Date);
}
// finally compare by the counter
return x.Counter.CompareTo(y.Counter);
}
}
另一种不那么吸引人的方法可能是一种扩展方法。遗憾的是,由于每个TKey
的{{1}}可能不同,我们会失去泛型的强大功能,但在这种情况下可以安全地用类型ThenBy
替换它。
object
答案 1 :(得分:2)
您必须实施IComparable<foo>
并比较所有属性:
class foo: IComparable<foo>, IComparer<foo>
{
public string name { get; set; }
public DateTime date { get; set; }
public int counter { get; set; }
public int Compare(foo x, foo y)
{
if (x == null || y == null) return int.MinValue;
if (x.name != y.name)
return StringComparer.CurrentCulture.Compare(x.name, y.name);
else if (x.date != y.date)
return x.date.CompareTo(y.date);
else if (x.counter != y.counter)
return x.counter.CompareTo(y.counter);
else
return 0;
}
public int CompareTo(foo other)
{
return Compare(this, other);
}
}
然后您可以这样使用OrderBy
:
var ordered = foos.OrderBy(f => f).ToList();
答案 2 :(得分:1)
扩展方法有什么问题?
答案 3 :(得分:1)
为什么不简单地比较你的价值观:
int Compare(foo x, foo y)
{
if (x== null && y == null)
return 0;
else if (x == null)
return -1;
else if (y == null)
return 1;
var nameComparision = string.Compare(x.name,y.name);
if (nameComparision != 0)
return nameComparision;
var dateComparision = x.date.CompareTo(y.date);
if (dateComparision != 0)
return dateComparision;
var counterComparision = x.counter.CompareTo(y.counter);
return counterComparision;
}