Bex
Bex

Reputation: 4918

Retrieving values from a Linq GroupBy

I have a datatable which contains a load of dates. I wanted to group these by date and give each row a count.

I have managed to do this by dong the following:

 IEnumerable query = from row in stats.AsEnumerable()
                     group row by row.Field<string>("date") into grp
                     select new { Date = grp.Key, Count = grp.Count(t => t["date"] != null) };

(where "stats" is the datatable)

I can see from debugging that this brings back the values all grouped as I need, but now I need to loop them and get each date and count.

My problem is I don't know how to retrieve the values!

I have a foreach loop

foreach (var rw  in query)
{
   string date = rw.Date; // <---- this is my problem?
}

I don't know what type my Ienumerable is to be able to reference the values in it!

So my question is how can I retrieve each date and count for each row by doing similar to the above?

I hope this makes sense!

Upvotes: 4

Views: 4473

Answers (3)

Shiv Kumar
Shiv Kumar

Reputation: 9799

This link on my blog should help you http://www.matlus.com/linq-group-by-finding-duplicates/

Essentially your type is an anonymous type so you can't reference it as a type but you can access the properties like you're trying to do.

I think I see your issue. If you're trying to return it from a method, you should define a type and reuturn it like shown below:

public IEnumerable<MyType> GetQuery()
{

  var query = from row in stats.AsEnumerable()
                    group row by row.Field<string>("date") into grp
                    select new { Date = grp.Key, Count = grp.Count(t => t["date"] != null) }; 

  foreach (var rw  in query)
  {
     yield return new MyType(rw.Date, rw.Count);
  }
}

declare your "query" variable using "var" as shown above.

Upvotes: 1

AakashM
AakashM

Reputation: 63338

Going by your comment "I am returning the query from a function", which I take to mean that you want to do the query in a method, return the data to the caller, and then iterate the data in the caller, I suggest you return a Dictionary<DateTime, int>, like this:

static Dictionary<DateTime, int> GetSummarisedData()
{
    var results = (
        from row in stats.AsEnumerable()
        group row by row.Field<string>("date") into grp
        select new { Date = grp.Key, Count = grp.Count(t => t["date"] != null) })
        .ToDictionary(val => val.Date, val => val.Count);

    return results;
}

then in the caller you can just

foreach (var kvp in GetSummarisedData())
{
    // Now kvp.Key is the date
    // and kvp.Value is the count
}

Upvotes: 0

DHN
DHN

Reputation: 4865

I guess you don't have access to the properties of the anonymous class because you're using IEnumerable query = .... Try var query = ... instead.

Upvotes: 0

Related Questions