我有一个相当复杂的场景,我需要确保列表中的项目已经排序。
首先,列表中的项目基于包含子结构的结构。
例如:
public struct topLevelItem
{
public custStruct subLevelItem;
}
public struct custStruct
{
public string DeliveryTime;
}
现在我有一个由topLevelItem组成的列表,例如:
var items = new List<topLevelItem>();
我需要一种方法来对DeliveryTime ASC进行排序。还增加了复杂性的是DeliveryTime字段是一个字符串。由于这些结构是可重用API的一部分,因此我无法将该字段修改为DateTime,也无法在topLevelItem类中实现IComparable。
任何想法如何做到这一点?
谢谢
答案 0 :(得分:7)
创建一个实现IComparer的新类型,并使用它的实例来比较对象。
public class topLevelItemComparer : IComparer<topLevelItem>
{
public int Compare(topLevelItem a, topLevelItem b)
{
// Compare and return here.
}
}
然后您可以像这样调用Sort():
var items = new List<topLevelItem>();
// Fill the List
items.Sort(new topLevelItemComparer());
答案 1 :(得分:6)
听起来你需要获得规范化的日期排序,即使你的日期表示为字符串,是吗?嗯,你可以使用LINQ的OrderBy
运算符,但你必须将字符串解析为日期以获得正确的结果:
items = items.OrderBy(item => DateTime.Parse(item.subLevelItem.DeliveryTime))
.ToList();
<强>更新强>
为了完整性,我添加了这个 - 这是我如何将ParseExact与Invariant文化结合使用的一个真实例子:
var returnMessagesSorted = returnMessages.OrderBy((item => DateTime.ParseExact(item.EnvelopeInfo.DeliveryTime, ISDSFunctions.GetSolutionDateTimeFormat(), CultureInfo.InvariantCulture)));
return returnMessagesSorted.ToList();
你总是可以实现一个单独的IComparer类,它并不好玩,但效果很好:
public class TopLevelItemComparer : IComparer<topLevelItem>
{
public int Compare( topLevelItem x, topLevelItem y )
{
return DateTime.Parse(x.subLevelItem.DeliveryTime).CompareTo(
DateTime.Parse(y.subLevelItem.DeliveryTime) );
}
}
items.Sort( new TopLevelItemComparer() );
请注意,.NET框架中的大多数Sort()
方法接受IComparer
或IComparer<T>
,这允许您重新定义任何类型的比较语义。通常情况下,您只需使用Comparer<T>.Default
- 或使用基本上为您提供此功能的重载。
答案 2 :(得分:4)
使用LINQ:
items = items.OrderBy(item => item.subLevelItem.DeliveryTime).ToList();
答案 3 :(得分:4)
如果要执行就地排序,那么可以使用带有Sort
参数的Comparison<T>
重载并传递匿名函数/ lambda:
items.Sort((x, y) => DateTime.Parse(x.subLevelItem.DeliveryTime).CompareTo(
DateTime.Parse(y.subLevelItem.DeliveryTime)));
如果你更喜欢创建一个新的排序序列而不是就地排序,那么LINQ的OrderBy
可能就像其他人已经提到过的那样。
答案 4 :(得分:2)
在我实现基于任意lambda表达式进行比较的LambdaComparer之前遇到此问题。不是确切的代码,而是这些内容:
public class LambdaComparer : IComparer<T>
{
private Func<T,T,int> _func;
public LambdaComparer(Func<T,T,int> function)
{
_func = function;
}
public int Compare(T x, T y)
{
return _func(x,y);
}
}
这样做的一大优点是你可以获得一个很好的可重用代码块。
答案 5 :(得分:1)
要对items
列表本身进行排序:
Comparison<topLevelItem> itemComparison = (x, y) => {
DateTime dx;
DateTime dy;
bool xParsed = DateTime.TryParse(x.subLevelItem.DeliveryTime, out dx);
bool yParsed = DateTime.TryParse(y.subLevelItem.DeliveryTime, out dy);
if (xParsed && yParsed)
return dx.CompareTo(dy);
else if (xParsed)
return -1; // or 1, if you want invalid strings to come first
else if (yParsed)
return 1; // or -1, if you want invalid strings to come first
else
// simple string comparison
return x.subLevelItem.DeliveryTime.CompareTo(y.subLevelItem.DeliveryTime);
};
items.Sort(itemComparison);
这种方法的优点是:
DateTime
值排序,而非字符串,但是 ...... DateTime
,则不会抛出异常(基本上,所有无效字符串最终都会出现在列表的一侧)