C # how to sort a list without implementing IComparable manually?

I have a rather complicated scenario, and I need the items that I have in the list to be sorted.

First, the items in the list are based on a structure containing a substructure.

For example:

public struct topLevelItem { public custStruct subLevelItem; } public struct custStruct { public string DeliveryTime; } 

Now I have a list consisting of topLevelItems, for example:

 var items = new List<topLevelItem>(); 

I need a sorting method in ASC DeliveryTime. In addition, the difficulty is that the DeliveryTime field is a string. Since these structures are part of the reusable API, I cannot change this field in DateTime, and I cannot implement IComparable in the topLevelItem class.

Any ideas how to do this?

thanks

+7
c #
source share
6 answers

It looks like you need to get canonical sorting by date, even if your date is presented as a string, right? Well, you can use the LINQ OrderBy operator, but you will need to parse the string in the date to achieve the correct results:

 items = items.OrderBy(item => DateTime.Parse(item.subLevelItem.DeliveryTime)) .ToList(); 

Update:

I added this for completeness - a true 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, this is 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() ); 

Remember that most Sort() methods on the .NET platform accept IComparer or IComparer<T> , which allows you to override the comparison semantics for any type. Usually you just use Comparer<T>.Default - or use an overload that essentially provides you with this.

+6
source share

Create a new type that implements IComparer and uses the instance to compare objects.

 public class topLevelItemComparer : IComparer<topLevelItem> { public int Compare(topLevelItem a, topLevelItem b) { // Compare and return here. } } 

Then you can call Sort () as follows:

 var items = new List<topLevelItem>(); // Fill the List items.Sort(new topLevelItemComparer()); 
+7
source share

Using LINQ:

 items = items.OrderBy(item => item.subLevelItem.DeliveryTime).ToList(); 
+4
source share

If you want to do in-place sorting, you can use the Sort overload, which takes Comparison<T> and passes the anonymous / lambda function:

 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 in-place sorting, then LINQ OrderBy is probably the transition method, as mentioned in others.

+4
source share

I had this problem before I once applied LambdaComparer, which made a comparison based on an arbitrary lambda expression. Not the exact code, but something like that:

 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); } } 

The big advantage of this is that you get a good multiple piece of code.

+2
source share

Sorting 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 that

  • Sort the list in place (that is, if you really want the list to be sorted in place)
  • Sort by actual DateTime values, not by rows, BUT ...
  • Do not throw an exception if the line does not represent a valid DateTime (basically, all invalid lines end on one side of the list)
+1
source share

All Articles