Reputation: 53
I have this one problem. There is a string
string [5] names = { "John", "Sam", "Harry", "Sam", "John" }
I need to find the most common elements in the array. I tried using :
string MostCommon = names.GroupBy(v => v)
.OrderByDescending(g => g.Count())
.First()
.Key;
Unfortunately it only finds one element, f.e., MostCommon = John
, and in this case I need not only John
, but Sam
too. How could I do that? Maybe LINQ is not necessary in this case?
Upvotes: 5
Views: 7422
Reputation: 21
//With Dictionary
//This is more useful if you are looking to interview big companies otherwise use the
Linq option which is short and handy
public static int MaxOccurrenceOfWord(string[] words)
{
var counts = new Dictionary<string, int>();
int occurrences = 0;
foreach (var word in words)
{
int count;
counts.TryGetValue(word, out count);
count++;
//Automatically replaces the entry if it exists;
//no need to use 'Contains'
counts[word] = count;
}
string mostCommonWord = null;
foreach (var pair in counts)
{
if (pair.Value > occurrences)
{
occurrences = pair.Value;
mostCommonWord = pair.Key;
}
}
Console.WriteLine("The most common number is {0} and it appears {1} times",
mostCommonWord, occurrences);
return occurrences;
}
Upvotes: 0
Reputation: 37000
First
will obviously only select the very first element of your sequence. However you need all groups with an equal number. So select the name and number per group and order afterwards. Finally select all those groups having the same count as the very first group.
var groups = names.GroupBy(x => x)
.Select(x => new { x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count);
int max = groups.First().Count;
var mostCommons = groups.Where(x => x.Count == max);
EDIT: You could also use TakeWhile
instead of Where
in the last statement which will avoid unnecessary comparisons for the last elements in the groups
-list and stops immediately when the first group was found having less elements than the first one:
var mostCommons = groups.TakeWhile(x => x.Count == groups.First().Count);
Upvotes: 12
Reputation: 2475
Combine your first LINQ with another similar linq based on the count of the most common name you found.
string MostCommon = names.GroupBy(v => v)
.OrderByDescending(g => g.Count())
.First();
int count = names.Where(x => x == MostCommon).Count();
var mostCommonList = names.GroupBy(v => v)
.Where(g => g.Count() == count);
Upvotes: 4
Reputation: 1450
This could be done as follows -
var nameGroup = names.GroupBy(x => x);
var maxCount = nameGroup.Max(g => g.Count());
var mostCommons = nameGroup.Where(x => x.Count() == maxCount).Select(x => x.Key).ToArray();
Upvotes: 5