2
List<int> a = new List<int>{ 1,1,2,2,3,4,5 };

What's the quickest way to do this with LINQ?

I'm new to LINQ

Mike
  • 47,263
  • 29
  • 113
  • 177

5 Answers5

16

The key here is using Enumerable.GroupBy and the aggregation method Enumerable.Count:

List<int> list = new List<int>() { 1,1,2,2,3,4,5 };

// group by value and count frequency
var query = from i in list
            group i by i into g
            select new {g.Key, Count = g.Count()};

// compute the maximum frequency
int whatsTheFrequencyKenneth = query.Max(g => g.Count);

// find the values with that frequency
IEnumerable<int> modes = query
                              .Where(g => g.Count == whatsTheFrequencyKenneth)
                              .Select(g => g.Key);

// dump to console
foreach(var mode in modes) {
    Console.WriteLine(mode);
}
jason
  • 236,483
  • 35
  • 423
  • 525
2

Jason's answer is correct, but you can perform this operation in one LINQ operation.

        List<int> list = new List<int>() { 1, 1, 2, 2, 3, 4, 5 };

        // return most frequently occurring items
        var query = from i in list
                    group i by i into g

                    let maxFreq = (from i2 in list 
                                  group i2 by i2 into g2
                                  orderby g2.Count() descending 
                                  select g2.Count()).First() 

                    let gCount = g.Count()

                    where gCount == maxFreq 

                    select  g.Key;

        // dump to console
        foreach (var mode in query)
        {
            Console.WriteLine(mode);
        }
2
public static Tres MostCommon<Tsrc, Tres>(this IEnumerable<Tsrc> source, Func<Tsrc, Tres> transform)
{
    return source.GroupBy(s => transform(s)).OrderByDescending(g => g.Count()).First().Key;
}

And in your example with integral types you can call it as:

List<int> a = new List<int>{ 1,1,2,2,3,4,5 };
int mostCommon = a.MostCommon(x => x);
Andrei
  • 1,015
  • 1
  • 11
  • 19
1
from num in a
group num by num into numg
let c = numg.Count()
order by c descending
select new { Number = numg.Key, Count = c }
yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • 1
    This only orders by frequency and computes frequency. It does not, however, find the item(s) that occured the most. – jason Jul 23 '09 at 02:55
0

I think the most frequent number can also be achieved in a single query like this-

  var query = (from i in list
               group i by i into g
               orderby g.Count() descending
               select new { Key = g.Key, Count = g.Count() }).FirstOrDefault();
  if (query == null) Console.WriteLine("query = NULL");
  else  Console.WriteLine("The number '{0}' occurs {1} times.", query.Key, query.Count);

Null check is not really required but it may be useful when null is actually expected (like Empty list?)

  • 1
    This method does not catch lists that have multiple items with the highest frequency. – jason Jul 23 '09 at 13:11