Home > Software engineering >  Sorting MM-YYYY string using custom comparer
Sorting MM-YYYY string using custom comparer

Time:01-05

How to perform sorting on the list of mm-yyyy strings along with mixed words using custom comparer with memory-optimized way.

List<string> result = new List<string>();
result.Add("04-2020");
result.Add("03-2021");
result.Add("Nan");

CodePudding user response:

You can achieve this using Linq and the use of DateTime.TryParseExact

var orderedList = result.OrderByDescending(x =>
        {
            DateTime dt;
            DateTime.TryParseExact(x, "MM-yyyy", CultureInfo.InvariantCulture,
                                   DateTimeStyles.None, out dt);
            return dt;
        }).ToList();

CodePudding user response:

You could use Linq as Ran suggested in his answer, and it will work nicely.
However there is another alternative that will probably be more memory-optimized (though admittedly I didn't check):

The List<T> type has a built in Sort method that have several overloads, one of them takes in a Comparison<T> delegate.

Using it will probably be better memory-optimized than using Linq, because you wouldn't need to allocate a new List<T>. Here's one way you can use it (of course, you can use a named method instead of a lambda expression):

        result.Sort((a, b) => { 
            var dateA = DateTime.TryParseExact(a, "MM-yyyy", CultureInfo.InvariantCulture,DateTimeStyles.None, out var dtA) ? dtA : DateTime.MinValue; // change to MaxValue if needed
            var dateB = DateTime.TryParseExact(b, "MM-yyyy", CultureInfo.InvariantCulture,DateTimeStyles.None, out var dtB) ? dtB : DateTime.MinValue; // change to MaxValue if needed
            return dateB.CompareTo(dateA); // Assending order
            return dateA.CompareTo(dateB); // Descending order
        });

CodePudding user response:

If you also want to sort the "non-dates", then you cannot ignore those (building on previous answers):

List<string> result = new List<string>();
result.Add("04-2020");
result.Add("03-2021");
result.Add("04-2021");
result.Add("2-2021");
result.Add("Nan");
result.Add("Aan");
result.Add("Xan");

var sorted = result.OrderBy(s =>
{
    DateTime dt;
    if (DateTime.TryParseExact(s, "M-yyyy",
            System.Globalization.CultureInfo.InvariantCulture, 
            System.Globalization.DateTimeStyles.None, out dt))
        return (dt, "");
    return (DateTime.MaxValue, s);
}).ToList();

This builds a tuple of (DateTime, string), with the date filled in when it did parse, otherwise only the string is filled (with the original string value).

Result:

04-2020
2-2021
03-2021
04-2021
Aan
Nan
Xan

  •  Tags:  
  • Related