w00
w00

Reputation: 26762

Group by and count in List

I have an List which is filled with ints, like this:

[0] 1
[1] 4
[2] 4
[3] 8
[4] 9
[5] 1
[6] 1

So basically random numbers in there, but the same number can occure multiple times in that list.

What i want is to group them by number, but that i can also tell how many times that number was in the list. So that i have a something like:

[0] 
  [number] 1
  [total] 3  // Occured 3 times in the list
[1]
  [number] 4
  [total] 2
[2]
  [number] 8
  [total] 1
[3]
  [number] 9
  [total] 1

Is there a fast/easy way to accomplish this? Or do i have the write out all sorts of loops and checks to construct something like this manually?

Upvotes: 23

Views: 58577

Answers (6)

pvsfair
pvsfair

Reputation: 320

Using only the GroupBy method you could do it like this:

var itemsResult = numbers.GroupBy(i => i,
                                  i => i,
                                  (keys, numbersGrouped) =>
                                      new{
                                          number = numbersGrouped.FirstOrDefault(),
                                          total = numbersGrouped.Count()
                                      }
                                  );

It outperforms the GroupBy + Select method proposed by the others executing in less than a half of the time comparing to the other implementations.

You can check below the performance comparison:

https://dotnetfiddle.net/0M2aKD

This is the docs for the function used if you want to check how does it works

Upvotes: 1

solmon
solmon

Reputation: 51

My solution:

var result = from i in n 
group i by i into g
select new {g.Key, Count= g.Count()};

Upvotes: 1

Marc
Marc

Reputation: 9354

Here's an example of all sorts of loops and checks:

var items = new Dictionary<int,int>();
foreach(var number in numbers)
{
   if(items.ContainsKey(number))
      items[number]++;
   else
      items.Add(number, 1);
}

Just for reference anyway. I prefer the LINQ approach, but it's not really as bad of a problem as you may have believed.

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460058

Use GroupBy and Count:

var numberGroups = numbers.GroupBy(i => i);
foreach(var grp in numberGroups)
{
    var number = grp.Key;
    var total  = grp.Count();
}

Here's another example which uses an anonymous type to store some informations. It also creates an array since it seems to be the desired result:

var numberGroups = numbers.GroupBy(i => i)
                   .Select(grp => new{
                       number  = grp.Key,
                       total   = grp.Count(),
                       average = grp.Average(),
                       minimum = grp.Min(),
                       maximum = grp.Max()
                   })
                   .ToArray();

foreach (var numInfo in numberGroups)
{
    var number = numInfo.number;
    // ...
    var maximum = numInfo.maximum;
}

Upvotes: 39

Jamie Dixon
Jamie Dixon

Reputation: 53991

Using Tims method from above with a Select rather than a foreach you could do:

var itemsByGroupWithCount = numbers.GroupBy(i => i)
                 .Select(item => new { 
                        Number = item.Key, 
                        Total = item.Count()});

Upvotes: 0

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48558

Use this

var result = numbers.GroupBy(n => n)
                    .Select(c => new { Key = c.Key, total = c.Count() });

Upvotes: 13

Related Questions