66

Is there a simple way to count the number of occurrences of all elements of a list into that same list in C#?

Something like this:

using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;

string Occur;
List<string> Words = new List<string>();
List<string> Occurrences = new List<string>();

// ~170 elements added. . . 

for (int i = 0;i<Words.Count;i++){
    Words = Words.Distinct().ToList();
    for (int ii = 0;ii<Words.Count;ii++){Occur = new Regex(Words[ii]).Matches(Words[]).Count;}
         Occurrences.Add (Occur);
         Console.Write("{0} ({1}), ", Words[i], Occurrences[i]);
    }
}
Jim
  • 2,974
  • 2
  • 19
  • 29
Nona Urbiz
  • 4,873
  • 16
  • 57
  • 84

7 Answers7

117

How about something like this ...

var l1 = new List<int>() { 1,2,3,4,5,2,2,2,4,4,4,1 };

var g = l1.GroupBy( i => i );

foreach( var grp in g )
{
  Console.WriteLine( "{0} {1}", grp.Key, grp.Count() );
}

Edit per comment: I will try and do this justice. :)

In my example, it's a Func<int, TKey> because my list is ints. So, I'm telling GroupBy how to group my items. The Func takes a int and returns the the key for my grouping. In this case, I will get an IGrouping<int,int> (a grouping of ints keyed by an int). If I changed it to (i => i.ToString() ) for example, I would be keying my grouping by a string. You can imagine a less trivial example than keying by "1", "2", "3" ... maybe I make a function that returns "one", "two", "three" to be my keys ...

private string SampleMethod( int i )
{
  // magically return "One" if i == 1, "Two" if i == 2, etc.
}

So, that's a Func that would take an int and return a string, just like ...

i =>  // magically return "One" if i == 1, "Two" if i == 2, etc. 

But, since the original question called for knowing the original list value and it's count, I just used an integer to key my integer grouping to make my example simpler.

JP Alioto
  • 44,864
  • 6
  • 88
  • 112
  • 1
    +1. this is very elegant to count the occurrence of each distinct elements. – Stan R. Jul 16 '09 at 18:01
  • 1
    FindAll returns a list of elements from the original list that match a predicate, so you would have to do it once for each unique element to find the count for that element. – JP Alioto Jul 16 '09 at 18:18
  • 1
    Just use it. Great solution. If you want to sort it, just use : `var g = l1.GroupBy( i => i ).OrderByDescending(group => group.Count());`. – aloisdg Apr 28 '14 at 18:44
25

You can do something like this to count from a list of things.

IList<String> names = new List<string>() { "ToString", "Format" };
IEnumerable<String> methodNames = typeof(String).GetMethods().Select(x => x.Name);

int count = methodNames.Where(x => names.Contains(x)).Count();

To count a single element

string occur = "Test1";
IList<String> words = new List<string>() {"Test1","Test2","Test3","Test1"};

int count = words.Where(x => x.Equals(occur)).Count();
nawfal
  • 70,104
  • 56
  • 326
  • 368
Stan R.
  • 15,757
  • 4
  • 50
  • 58
  • 1
    +1: It took me awhile to figure out that GetMethods() was just your list of things. :) – Robert Harvey Jul 16 '09 at 18:05
  • yeah, I thought of that and decided to make it more readable. thanks, although I misread the question. It says to count "all the element"..ooops. This should still be useful enough. – Stan R. Jul 16 '09 at 18:06
  • @StanR. - this solution works for my problem. However, is there a method on the list where I can count the occurrence greater than or equal to in words? I am using "int" type instead of "string." – Mihir Patel Mar 01 '17 at 16:07
  • @MihirPatel just change the .Where to x > num || x == num – Stan R. Mar 01 '17 at 18:50
15
var wordCount =
    from word in words
    group word by word into g
    select new { g.Key, Count = g.Count() };    

This is taken from one of the examples in the linqpad

Steve Mitcham
  • 5,268
  • 1
  • 28
  • 56
2
public void printsOccurences(List<String> words)
{
    var selectQuery =
        from word in words
        group word by word into g
        select new {Word = g.Key, Count = g.Count()};
    foreach(var word in selectQuery)
        Console.WriteLine($"{word.Word}: {word.Count}");*emphasized text*
}
The Artist
  • 21
  • 1
1

This is a version which avoids Linq but uses only slightly more code.

// using System.Collections.Generic;

Dictionary<int, int> oGroups = new Dictionary<int, int>();
List<int> oList = new List<int>() { 1, 2, 3, 4, 5, 2, 2, 2, 4, 4, 4, 1 };

foreach (int iCurrentValue in oList)
{
    if (oGroups.ContainsKey(iCurrentValue))
        oGroups[iCurrentValue]++;
    else
        oGroups.Add(iCurrentValue, 1);
}

foreach (KeyValuePair<int, int> oGroup in oGroups)
{
    Console.WriteLine($"Value {oGroup.Key} appears {oGroup.Value} times.");
}
Ed H
  • 11
  • 1
0

this code returns a dictionary that contain the world and the occurrence:

            var wordsDic = Words
            .GroupBy(p => p)
            .ToDictionary(p => p.Key, q => q.Count());
Mojtaba Karimi
  • 426
  • 7
  • 10
-4

Your outer loop is looping over all the words in the list. It's unnecessary and will cause you problems. Remove it and it should work properly.

SuperJMN
  • 13,110
  • 16
  • 86
  • 185
Paul Sonier
  • 38,903
  • 3
  • 77
  • 117