Ryan Ische
Ryan Ische

Reputation: 3656

Building a dictionary of counts of items in a list

I have a List containing a bunch of strings that can occur more than once. I would like to take this list and build a dictionary of the list items as the key and the count of their occurrences as the value.

Example:

List<string> stuff = new List<string>();
stuff.Add( "Peanut Butter" );
stuff.Add( "Jam" );
stuff.Add( "Food" );
stuff.Add( "Snacks" );
stuff.Add( "Philosophy" );
stuff.Add( "Peanut Butter" );
stuff.Add( "Jam" );
stuff.Add( "Food" );

and the result would be a Dictionary containing:

"Peanut Butter", 2
"Jam", 2
"Food", 2
"Snacks", 1
"Philosophy", 1

I have a way to do this, but it doesn't seem like I'm utilizing the good stuff in C# 3.0

public Dictionary<string, int> CountStuff( IList<string> stuffList )
{
    Dictionary<string, int> stuffCount = new Dictionary<string, int>();

    foreach (string stuff in stuffList) {
        //initialize or increment the count for this item
        if (stuffCount.ContainsKey( stuff )) {
            stuffCount[stuff]++;
        } else {
            stuffCount.Add( stuff, 1 );
        }
    }

    return stuffCount;
}

Upvotes: 16

Views: 19324

Answers (5)

casperOne
casperOne

Reputation: 74530

You can use the group clause in C# to do this.

List<string> stuff = new List<string>();
...

var groups = 
    from s in stuff
    group s by s into g
    select new { 
        Stuff = g.Key, 
        Count = g.Count() 
    };

You can call the extension methods directly as well if you want:

var groups = stuff
    .GroupBy(s => s)
    .Select(s => new { 
        Stuff = s.Key, 
        Count = s.Count() 
    });

From here it's a short hop to place it into a Dictionary<string, int>:

var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);

Upvotes: 35

Aryan Firouzian
Aryan Firouzian

Reputation: 2016

Dictionary<string, int> a = stuff.GroupBy(p => p).OrderByDescending(r=>r.Count()).ToDictionary(q => q.Key, q => q.Count());

You can GroupBy and then create dictionary to count each group. As performance test indicate, usually there are more efficient approaches other than Linq. I think your code is more efficient, while Linq solution is more readable and beautiful.

Upvotes: 1

sfossen
sfossen

Reputation: 4778

I would have made a specialized List, that backed by the Dictionary and the add method would test for membership and increase count if found.

sorta like:

public class CountingList
{
    Dictionary<string, int> countingList = new Dictionary<string, int>();

   void Add( string s )
   {
        if( countingList.ContainsKey( s ))
             countingList[ s ] ++;
        else
            countingList.Add( s, 1 );
   }
}

Upvotes: 9

Guffa
Guffa

Reputation: 700362

Well, there isn't really any better way to do it.

Perhaps you could write a LINQ query that would group the strings and then count how many strings there are in each group, but that would not be nearly as efficient as what you already have.

Upvotes: 0

MarkusQ
MarkusQ

Reputation: 21950

One idea would be to give the dictionary a default value of zero, so you wouldn't have to special case the first occurrence.

Upvotes: 1

Related Questions