Willian Soares
Willian Soares

Reputation: 320

How make a LINQ Select, GroupBy and Count from a List of Lists?

I have a List<IEnumerable<Foo>>

This makes an list like this:

{
    [
      {a: 1, b: 2},
      {a: 1, b: 3}
    ],
    [{a: 1, b: 2}]
}

And i need to arrange it in this way, grouping the objects by the a and b values. I was no able to make a group query to anything like the example below.

{
   {a: 1, b: 2, count: 2},
   {a: 1, b: 3, count: 1}
} 

Edit: Here's the code that i have and the output:

var list = new List<object>();
foreach (var f in fooList)
{
    var x = from y in f
            group y by new { y.a, y.b } into z
            select new
            {
                Foo = z.Key,
                Count = z.Count()
            };
    a.Add(x);
}

Output:

[
  {
     "Foo": {
         "a": 1,
         "b": 2
     },
     "count": 1
  },
  {
     "Foo": {
         "a": 1,
         "b": 2
     },
     "count": 1
  },
  {
     "Foo": {
         "a": 1,
         "b": 3
     },
     "count": 1
  }
],

Upvotes: 1

Views: 1328

Answers (2)

Guillaume CR
Guillaume CR

Reputation: 3016

You have to flatten your first list, as the nested level is irrelevant to your desired result. This shows how to flatten. I think your GroupBy is correct.

    List<List<Foo>> list = new List<List<Foo>>();
    list.Add(new List<Foo>());
    list[0].Add(new Foo { a = 1, b = 2 });
    list[0].Add(new Foo { a = 1, b = 3 });
    var subList = new List<Foo>();
    subList.Add(new Foo { a = 1, b = 2 });
    list.Add(subList);
    var flat = list.SelectMany(i => i);
    var grouped = from foo in flat group foo by new { foo.a, foo.b } into g select g;
    Assert.AreEqual(true, grouped.First().Count() == 2);
    Assert.AreEqual(true, grouped.Last().Count() == 1);

Upvotes: 0

croxy
croxy

Reputation: 4170

Something like this will work:

var list = new List<List<Foo>>();
list.Add(new List<Foo> {new Foo {A = 1, B = 2}, new Foo {A = 1, B = 3}});
list.Add(new List<Foo> {new Foo {A = 1, B = 2}});

var result = list.SelectMany(l => l)
    .GroupBy(l => new {l.A, l.B})
    .Select(grp => new {A = grp.Key.A, B = grp.Key.B, Count = grp.Count()});

First the list gets flattened with SelectMany(). After that we GroupBy multiple values by using an anonymous object. After grouping we are selecting the initial values and the count out of the grouping into an anonymous object.


It seems like you want your result to be serialized. Using Json.Net, this will be the output:

[
   {
      "A":1,
      "B":2,
      "Count":2
   },
   {
      "A":1,
      "B":3,
      "Count":1
   }
]

Upvotes: 1

Related Questions