If a method written in C# will be passed either a null or somewhere between 0 to 6,000,000 randomly generated and unsorted integers, what is the most efficient way to determine all modes and how many times they occurred? In particular, can anyone help me with a LINQ based solution, which I'm struggling with?
Here is what I have so far:
My closest LINQ solution so far only grabs the first mode it finds and does not specify the number of occurrences. It is also about 7 times as slow on my computer as my ugly, bulky implementation, which is hideous.
int mode = numbers.GroupBy(number => number).OrderByDescending(group => group.Count()).Select(k => k.Key).FirstOrDefault();
My manually coded method.
public class NumberCount
{
public int Value;
public int Occurrences;
public NumberCount(int value, int occurrences)
{
Value = value;
Occurrences = occurrences;
}
}
private static List<NumberCount> findMostCommon(List<int> integers)
{
if (integers == null)
return null;
else if (integers.Count < 1)
return new List<NumberCount>();
List<NumberCount> mostCommon = new List<NumberCount>();
integers.Sort();
mostCommon.Add(new NumberCount(integers[0], 1));
for (int i=1; i<integers.Count; i++)
{
if (mostCommon[mostCommon.Count - 1].Value != integers[i])
mostCommon.Add(new NumberCount(integers[i], 1));
else
mostCommon[mostCommon.Count - 1].Occurrences++;
}
List<NumberCount> answer = new List<NumberCount>();
answer.Add(mostCommon[0]);
for (int i=1; i<mostCommon.Count; i++)
{
if (mostCommon[i].Occurrences > answer[0].Occurrences)
{
if (answer.Count == 1)
{
answer[0] = mostCommon[i];
}
else
{
answer = new List<NumberCount>();
answer.Add(mostCommon[i]);
}
}
else if (mostCommon[i].Occurrences == answer[0].Occurrences)
{
answer.Add(mostCommon[i]);
}
}
return answer;
}
Basically, I'm trying to get an elegant, compact LINQ solution at least as fast as my ugly method. Thanks in advance for any suggestions.