LINQ - Group List<T> to Year, Month, Day

1.6k Views Asked by At

I have a simple list

  • T.Date = 11/04/2014, T.Title = "Book1", T.Tipology = "Book"
  • T.Date = 14/04/2014, T.Title = "Book2", T.Tipology = "Book"
  • T.Date = 02/05/2015, T.Title = "Spot1", T.Tipology = "Spot"
  • T.Date = 21/06/2015, T.Title = "Newspaper1", T.Tipology = "Newspaper"

I need to group this list by Year, Month and Day as below:

  • 2014
    • April
      • T.Date = 11/04/2014, T.Title = "Book1", T.Tipology = "Book"
      • T.Date = 14/04/2014, T.Title = "Book2", T.Tipology = "Book"
  • 2015
    • May
      • T.Date = 02/05/2015, T.Title = "Spot1", T.Tipology = "Spot"
    • June
      • T.Date = 21/06/2016, T.Title = "Newspaper1", T.Tipology = "Newspaper"

So i will able to process data in a foreach function like:

 foreach(var year in Year)
 {
     foreach(var month in Month)
     {
         foreach(var day in Day)
         {
            Console.WriteLine(day.Item.Title);
            Console.WriteLine(day.Item.Tipology);
         }
         Console.WriteLine(month.ToString()); // With culture
     }
     Console.WriteLine(year.ToString());
 }

How I can do this with (c#) LINQ?

4

There are 4 best solutions below

0
On BEST ANSWER

You can use nested groups.

var groups = list
            .GroupBy(
                    d => d.Date.Year, 
                    (key, g) => g.GroupBy(
                                          d => d.Date.Month,
                                          (key2, g2) => g2.GroupBy(d => d.Date)
                                         )
                    );
4
On

You can order them by year, month and day:

var sorted = list.OrderBy(x=>x.Date.Year)
                 .ThenBy(x=>x.Date.Month)
                 .ThenBy(x=>x.Date.Day);

If you really want to group them then you can do something like:

var result = from l in list
             group l by new { l.Date.Year,l.Date.Month} into g 
             select new
                   {
                     Year = g.Key.Year,
                     Month = g.Key.Month,
                     Items = g.ToList()
                    };

so it will give you grouped data on every year month dates

0
On

Your object can inherit from IComparable, and than just order by your object.

2
On

You could order the list and then keep track of the last book:

var orderedBooks = books.OrderBy(x => x.Date.Year).ThenBy(x => x.Date.Month).ThenBy(x => x.Date.Day);
Book last = null;
foreach (Book book in orderedBooks)
{
    Console.WriteLine(book.Title);
    Console.WriteLine(book.Tipology);
    if(last != null  && last.Date.Month != book.Date.Month)
        Console.WriteLine(DateTimeFormatInfo.CurrentInfo.GetAbbreviatedMonthName(book.Date.Month)); // With culture
    if (last != null && last.Date.Year != book.Date.Year)
        Console.WriteLine(book.Date.Year.ToString()); 
    last = book;
}