I have a fairly complex scenario and I need to ensure items I have in a list are sorted.
Firstly the items in the list are based on a struct that contains a sub struct.
For example:
public struct topLevelItem
{
public custStruct subLevelItem;
}
public struct custStruct
{
public string DeliveryTime;
}
Now I have a list comprised of topLevelItems for example:
var items = new List<topLevelItem>();
I need a way to sort on the DeliveryTime ASC. What also adds to the complexity is that the DeliveryTime field is a string. Since these structs are part of a reusable API, I can't modify that field to a DateTime, neither can I implement IComparable in the topLevelItem class.
Any ideas how this can be done?
Thank you
Create a new type that implements IComparer and use an instance of it to compare the objects.
public class topLevelItemComparer : IComparer<topLevelItem>
{
public int Compare(topLevelItem a, topLevelItem b)
{
// Compare and return here.
}
}
You can then call Sort() like this:
var items = new List<topLevelItem>();
// Fill the List
items.Sort(new topLevelItemComparer());
It sounds like you need to get canonicalized date sorting even though your date is represented as a string, yes? Well, you can use LINQ's OrderBy
operator, but you will have to parse the string into a date to achieve correct results:
items = items.OrderBy(item => DateTime.Parse(item.subLevelItem.DeliveryTime))
.ToList();
Update:
I've added this in for completeness - a real example of how I use ParseExact with Invariant culture:
var returnMessagesSorted = returnMessages.OrderBy((item => DateTime.ParseExact(item.EnvelopeInfo.DeliveryTime, ISDSFunctions.GetSolutionDateTimeFormat(), CultureInfo.InvariantCulture)));
return returnMessagesSorted.ToList();
You can always implement a separate IComparer class, it's not fun, but it works well:
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() );
Be aware that most Sort()
methods in the .NET framework accept an IComparer
or IComparer<T>
which allows you to redefine the comparison semantics for any type. Normally, you just use Comparer<T>.Default
- or use an overload that essentially supplies this for you.
使用LINQ:
items = items.OrderBy(item => item.subLevelItem.DeliveryTime).ToList();
If you want to perform an in-place sort then you can use the Sort
overload that takes a Comparison<T>
argument and pass an anonymous function/lambda:
items.Sort((x, y) => DateTime.Parse(x.subLevelItem.DeliveryTime).CompareTo(
DateTime.Parse(y.subLevelItem.DeliveryTime)));
If you prefer to create a new sorted sequence rather than an in-place sort then LINQ's OrderBy
is probably the way to go, as others have already mentioned.
Having had this problem before I once implemented a LambdaComparer that did the compare based on an arbitrary lambda expression. Not exact code but something along these lines:
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);
}
}
Big advantage of this is you get a nice reusable chunk of code.
To sort the items
list itself:
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);
This approach has the advantage of:
DateTime
values, rather than strings, BUT ... DateTime
(basically, all the invalid strings will end up on one side of the list)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.