Domzaza
Domzaza

Reputation: 53

C# Find most common strings in string array

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

Answers (4)

Nilanjan
Nilanjan

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

MakePeaceGreatAgain
MakePeaceGreatAgain

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

dckuehn
dckuehn

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

Amit Hasan
Amit Hasan

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

Related Questions