0

I have a list "Sites" with one of the items as "From" and "To". It is defined as string and is in the format "MM/yyyy". When I try to sort the list based on the year, I'm facing a small problem.

Data for "From" and "To" is

01/2012
04/2012
01/2013
06/2012

When I sort the list by using orderby, the output I'm getting is

01/2012
01/2013
04/2012
06/2012

which is incorrect.

List<Site> List = new List<Site>();
                DataSet DS = ClientDB.Sites(Id);
                if (DS.HasTable0AndRows())
                {
                    IEnumerable<DataRow> _DataRow = DS.Tables[0].AsEnumerable();
                   List = _DataRow.Select(x => new Site()
                    {
                        FileNum = x["File_Num"].ToString(),
                        From = x["From"].ToString(),
                        To = x["To"].ToString(),
                    }).ToList();
                }
                return List.OrderBy(x => x.FileNum).ToList();
            }

I understand that I have to use DateTime.Parse inorder to convert the From and To but how do I use the DateTime.Parse in the above case when i return the list?

ERR
  • 415
  • 2
  • 6
  • 20

3 Answers3

5

You need custom comparer.

class DateComparer : IComparer<string>
{
    public int Compare(string a, string b)
    {
        var a_date = DateTime.ParseExact(a, "MM/yyyy", null);
        var b_date = DateTime.ParseExact(b, "MM/yyyy", null);
        return a_date.CompareTo(b_date);
    }
}

Usage:

return List.OrderBy(x => x.From, new DateComparer()).ToList();
Uladzimir Palekh
  • 1,846
  • 13
  • 16
  • Can you please explain me how it is working in the above solution? – ERR Feb 06 '17 at 22:56
  • You can pass custom comparer to the `OrderBy` function. This comparer will be used to compare items during sorting. My `DateComparer` converts `string` values to the `DateTime` using `DateTime.ParseExact` and returns result of dates comparison. Please note that my solution is not optimal from the performance side. It will be better to convert dates once as proposed by Thomas D. If you still need string representation, you can use additional fields to store dates as `DateTime`. – Uladzimir Palekh Feb 06 '17 at 23:09
0

This should do the trick:

List<Site> List = new List<Site>();
DataSet DS = ClientDB.Sites(Id);
if (DS.HasTable0AndRows())
{
  IEnumerable<DataRow> _DataRow = DS.Tables[0].AsEnumerable();
  List = _DataRow.Select(x => new Site()
  {
    FileNum = x["File_Num"].ToString(),
    From = DateTime.ParseExact(x["From"].ToString(), "mm/yyyy", CultureInfo.InvariantCulture),
    To = DateTime.ParseExact(x["To"].ToString(), "mm/yyyy", CultureInfo.InvariantCulture),
  }).ToList();
}
return List.OrderBy(x => x.From).ToList();

I am assuming that you want the From and To of type DateTime instead of string.

If you want to keep the types to be strings then you should use Uladzimir Palekh answer.

Thomas D.
  • 1,031
  • 6
  • 17
  • How do i handle null values in this case? – ERR Feb 06 '17 at 23:29
  • @ananthreddy, it depends from what you want to do with nulls. Now your sample code will fail. But you always can use nullables to store nulls. – Uladzimir Palekh Feb 06 '17 at 23:35
  • @ananthreddy another possibility would be to use the TryParseExact method. https://msdn.microsoft.com/de-de/library/h9b85w22(v=vs.110).aspx – Thomas D. Feb 07 '17 at 06:57
0

If you problem is not solved yet use this:

Add this function beside your method:

    public int Compare(string a)
    {
        string[] arr = a.Split('/');
        return int.Parse(arr[1] + arr[0]);
    }

And use like this sample:

     List<string> dates = new List<string> { "01/2012", "04/2012", "01/2013", "06/2012" };
     dates = dates.OrderBy<string,int>(Compare).ToList();
Farzin Kanzi
  • 3,380
  • 2
  • 21
  • 23