Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this the best way to create a frequency table using LINQ?

Tags:

c#

linq

I want to write a function that reads a file and counts the number of times each word occurs. Assuming the file-reading is handled and produces a list of strings representing each line in the file, I need a function to count the occurrence of each word. Firstly, is using a Dictionary<string,int> the best approach? The key is the word, and the value is the number of occurrences of that word.

I wrote this function which iterates through each line and each word in a line and builds up a dictionary:

static IDictionary<string, int> CountWords(IEnumerable<string> lines)
var dict = new Dictionary<string, int>();
foreach (string line in lines)
{
    string[] words = line.Split(' ');
    foreach (string word in words)
    {
        if (dict.ContainsKey(word))
            dict[word]++;
        else
            dict.Add(word, 1);
    }
}

However, I would like to somehow write this function.. functionally, using LINQ (because LINQ is fun and I'm trying to improve my functional programming skills :D) I managed to come up with this expresion, but I'm not sure whether it's the best way to do it functionally:

static IDictionary<string, int> CountWords2(IEnumerable<string> lines)
{
    return lines
        .SelectMany(line => line.Split(' '))
        .Aggregate(new Dictionary<string, int>(),
            (dict, word) =>
            {
                if (dict.ContainsKey(word))
                    dict[word]++;
                else
                    dict.Add(word, 1);
                return dict;
            });
}

So while I have two working solutions, I am also interested in learning what the best approach is to this problem. Anyone with insight on LINQ and FP?

like image 713
guhou Avatar asked Dec 12 '22 20:12

guhou


1 Answers

As Tim Robinson wrote you could use GroupBy with ToDictionary like this

    public static Dictionary<string, int> CountWords3(IEnumerable<string> strings)
    {
        return strings.SelectMany(s => s.Split(' ')).GroupBy(w=>w).ToDictionary(g => g.Key, g => g.Count());
    }
like image 91
Yury Tarabanko Avatar answered Mar 18 '23 11:03

Yury Tarabanko