Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count Occurrences of an Item in a List using LINQ

I am trying to calculate the occurrences of an Item in a list using LINQ,

I have the following schema -

User (All Entries Provided), Count (To be Calculated)

The count should be like -

enter image description here

I cannot think of an elegant solution to this.

Is it even possible only using LINQ? If not, how can we achieve this using LINQ with some C# Code.

like image 429
Rajat Suneja Avatar asked Feb 12 '14 16:02

Rajat Suneja


2 Answers

You can do that with a combination of loop and Enumerable.Take, Something like:

for (int i = 0; i < list.Count; i++)
{
    //Get count of current element to before:
    int count = list.Take(i+1)
                    .Count(r => r.UserName == list[i].UserName);
    list[i].Count = count;
}

Where your list is defined as:

List<User> list = new List<User>
    {
        new User{UserName = "A"},
        new User{UserName = "B"},
        new User{UserName = "A"},
        new User{UserName = "A"},
        new User{UserName = "B"},
        new User{UserName = "A"},
        new User{UserName = "C"},
        new User{UserName = "A"},

    };

and User class as:

public class User
{
    public string UserName { get; set; }
    public int Count { get; set; }
}

Later you can print the output like:

foreach (var item in list)
{
    Console.WriteLine("UserName: {0}, Running Total: {1}", item.UserName, item.Count);
}

and you will get:

UserName: A, Running Total: 1
UserName: B, Running Total: 1
UserName: A, Running Total: 2
UserName: A, Running Total: 3
UserName: B, Running Total: 2
UserName: A, Running Total: 4
UserName: C, Running Total: 1
UserName: A, Running Total: 5
like image 193
Habib Avatar answered Sep 30 '22 11:09

Habib


Can it be done with LINQ? Probably not easily. Can it be done with your own extension method fairly easily? Sure (I haven't actually tried to compile and run the code so I can't guarantee that it'll work, but it's definitely a good starting point):

public static IEnumerable<Tuple<T, int>> RunningTotal<T>(this IEnumerable<T> source)
{
    var counter = new Dictionary<T, int>();

    foreach(var s in source)
    {
        if(counter.ContainsKey(s))
        {
            counter[s]++;
        }
        else
        {
            counter.Add(s, 1);
        }

        yield return Tuple.Create(s, counter[s]);
    }
}
like image 44
Justin Niessner Avatar answered Sep 30 '22 12:09

Justin Niessner