unable to Preserve property after group by linq

I have a collection of usages as follows and need the following output as below :

This is my Usage class :

public class Usage
{
    public Usage()  {}
    public string Alias { get; set; }
    public int ActivityCount { get; set; }
    public DateTime HitDate { get; set; }

}

This is my code :

I want to first group the collection into Users and for each user , i want to get a count of hits per day as shown in the EXPECTED output below. Note that date times a and d are different times in the same day , so they need to be grouped together .

This I am going to use to plot into bar graph of hits vs date i.e hits per day

On doing this , I am unable to preserve the alias field data into my second level grouping :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace NullOperator
{
    class Program
{
    static void Main(string[] args)
    {
        var a = new DateTime(2015, 10, 23, 12, 05, 06);
        var b = new DateTime(2015, 10, 24, 12, 05, 06);
        var c = new DateTime(2015, 10, 25, 12, 05, 06);
        var d = new DateTime(2015, 10, 23, 14, 05, 06);

        var usages = new List<Usage>
        {
            new Usage{Alias = "A ",HitDate = a},
            new Usage{Alias = "A ",HitDate = a},
            new Usage{Alias = "A ",HitDate = d},
            new Usage{Alias = "A ",HitDate = b},
            new Usage{Alias = "A ",HitDate = b},
            new Usage{Alias = "A ",HitDate = b},
            new Usage{Alias = "A ",HitDate = c},


            new Usage{Alias = "B ",HitDate = a},
            new Usage{Alias = "B ",HitDate = b},
            new Usage{Alias = "B ",HitDate = b},
            new Usage{Alias = "B ",HitDate = c},
            new Usage{Alias = "B ",HitDate = c},
            new Usage{Alias = "B ",HitDate = c},

            new Usage{Alias = "C ",HitDate = a},
            new Usage{Alias = "C ",HitDate = a},
            new Usage{Alias = "C ",HitDate = a},
            new Usage{Alias = "C ",HitDate = c},
            new Usage{Alias = "C ",HitDate = c},
            new Usage{Alias = "C ",HitDate = c},
        };

        var g = usages.GroupBy(r => r.Alias);

        foreach (var u in g)
        {          
            var x = u.GroupBy(r => r.HitDate.Day).Select(gr=>new
            {
                HitDate=gr.Key,
                Count=gr.Count()
            });

            foreach (var m in x)
            {
                Console.WriteLine(m.HitDate + "  " +m.Count);
            }
        }

        Console.Read();
    }
}

// EXPECTED OUTPUT

Alias : HitDate.Date  : hitcount
//  A  - 23/10/2015  - 3
//  A  - 24/10/2015 - 3
//  A  - 25/10/2015 - 1

//  B  - 23/10/2015 - 1
//  B  - 24/10/2015 - 2
//  B  - 25/10/2015 - 3

//  C  - 23/10/2015 - 3
//  C  - 24/10/2015- 0
//  C - 25/10/2015 -  3

OBTAINED OUTPUT :

23  3
24  3
25  1
23  1
24  2
25  3
23  3
25  3

As you can see , the grouping is alright , but some information like entire Date and Alias are lost and am not able to retrieve them in the code in the nested loop.

Any suggestions on this ? On how to get the required output?

Jon Skeet
people
quotationmark

Basically there are two problems here:

  • You're grouping by Day rather than Date, which I doubt you want to do
  • You're not using the fact that you've already got the alias as the key in the outer grouping

You can actually do this more simply by grouping by alias and date in one go though:

var query = usages.GroupBy(r => new { r.Alias, r.HitDate.Date },
                           (key, elements) => new { key.Alias,
                                                    key.Date,
                                                    Count = elements.Count() })
                  .OrderBy(x => x.Alias)
                  .ThenBy(x => x.Date);

foreach (var item in query)
{
    Console.WriteLine("{0} {1} {2}", item.Alias, item.Date, item.Count);
}

people

See more on this question at Stackoverflow