Dear all,

As the title says: How can I get the most frequent string (that occurred the most) in an array of strings ?

There is probably a .NET method for this, but Edward's first thought was to do it manually with a dictionary.

public string MostFrequent(string[] arr)
{
    var freq = new Dictionary<string, int>();

    Array.ForEach(arr, s => freq[s] = freq.ContainsKey(s) ? freq[s] + 1 : 1);

    return (from x in freq orderby x.Value ascending select x).Last().Key;
}

There is probably a more efficient way, and probably a shorter way, but that is what Ed came up with on short notice. ;)

Hi Niemo :icon_wink: this a very old fashion way but at least it works

static string Frequant(int no,string[]s) 
        {
            double[] x = new double[no];
            int i, j;
            for (i = 0; i < no; i++)
                x[i] = 0;
            for (j = 0; j < no; j++)
            {
                for (i = 0; i < no; i++)
                {
                    if (s[j] == s[i] && i != j)
                        x[j]++;
                }
            }
            double max = 0;
            int index = 0;
            for (i = 0; i < no; i++)
            {
                if (x[i] >= max)
                {
                    max = x[i];
                    index = i;
                }
            }
            return s[index];
        }

Here are two methods, one being a LINQ one-liner, the other being similar to Edward's with a dictionary.

static T GetMostFrequentWithLinq<T>(IEnumerable<T> list)
{
    return list.GroupBy(val => val).OrderByDescending(grp => grp.Count()).Select(grp => grp.Key).First();
}

static T GetMostFrequent<T>(IEnumerable<T> list)
{
    Dictionary<T, int> dictionary = new Dictionary<T, int>();

    int maxCount = 0;
    T maxItem = default(T);

    int currentCount = 0;

    foreach (T item in list)
    {
        if (dictionary.ContainsKey(item))
            currentCount = ++dictionary[item];
        else
            dictionary[item] = currentCount = 1;

        if (currentCount > maxCount)
        {
            maxCount = currentCount;
            maxItem = item;
        }
    }

    return maxItem;
}

The second should be more efficient, as it only needs a single pass over the list, and lookups in dictionaries are fast. But for small lists, it might not be evident and really doesn't matter.

Edited 6 Years Ago by apegram: n/a

Comments
Linq is still too hard for Ed's weak mind. ;)
The LINQ master has spoken!

You could do it without the dictionary by sorting the array then finding the longest sequence. Of course, this requires altering the element order and is less generic (can't sort IEnumerable). Here's apegram's code modified to do that:

T GetMostFrequent<T>(T[] list) where T : class
    {
        Array.Sort(list);

        int currentCount = 0;
        int maxCount = 0;
        T prevItem = null;
        T maxItem = null;

        foreach (T item in list)
        {
            if (++currentCount >= maxCount)
            {
                maxCount = currentCount;
                maxItem = item;
            }

            if (item != prevItem)
                currentCount = 1;
            else
               prevItem = item;
        }

        return maxItem;
    }
This article has been dead for over six months. Start a new discussion instead.