This is the kind of task for which LINQ is well-suited.
First, let's define what we're doing:
- Group the items by value
- Count each group
- Return the item whose group has the highest count
This query implements the above:
private string GetMostFrequent(IEnumerable<string> items)
{
var itemsOrderedByCount =
from item in items
group item by item into itemGroup
orderby itemGroup.Count() descending, itemGroup.Key
select itemGroup.Key;
return itemsOrderedByCount.FirstOrDefault();
}
The implementation reads very much like the high-level description, a nice side-effect of the declarative syntax. Here is a quick explanation of each part:
from item in items
is like a loop declaration; item
refers to the loop variable.
group item by item into itemGroup
This puts each item
in a group based on its value.
orderby itemGroup.Count() descending, itemGroup.Key
This counts each group and sorts them such that the most frequent is first. If there are two groups with the same count, the lesser value is chosen. (As each group contains all the same values, the key is the counted item.)
select itemGroup.Key
This says that for each group, we just want the counted item.
return itemsOrderedByCount.FirstOrDefault();
This grabs the first item in the ordered list (the one with the highest count). If the original sequence is empty, null is returned.
Usage:
var items = new[] { "BOB", "JOHN", "TOM", "TOM", "TOM" };
Assert.AreEqual("TOM", GetMostFrequent(items));