user6634447 user6634447 - 2 months ago 13
C# Question

get occurrence of string in generic list

I have a list like listed below, I need count of occurrence of time to be updated in occurrence count, Its not just getting total occurrence of string in list, Suppose Group1 is appearing second time occurrence count of that item should be updated as 2, If it appears one more time that particular occurrence should be updated as 3. This can be done using a loop and increment the count according to occurrence of group, Is there any better way to do this using linq or some other technique.

For example, with the following list:

public class Category
{
public long Id { get; set; }
public string Name { get; set; }

public int OccuranceCount { get; set; }
}

static void Main(string[] args)
{
var categories = new List<Category>
{
new Category {Id = 1, Name = "Group"},
new Category {Id = 1, Name = "Group2"},
new Category {Id = 1, Name = "Group1"},
new Category {Id = 1, Name = "Group2"},
new Category {Id = 1, Name = "Group"},
new Category {Id = 1, Name = "Group3"},
new Category {Id = 1, Name = "Group"}
};

Console.ReadKey();
}


I need to output something like this:

Name Occurrence Count
Group 0
Group2 0
Group1 0
Group2 1
Group 1
Group3 0
Group 2


My currrent code

foreach (var category in categories)
{
var selectedCategory = categories.Where(x => x.Name.Equals(category.Name));

category.OccuranceCount =
categories.Where(x => x.Name.Equals(category.Name)).Max(x => x.OccuranceCount) + 1;
}
foreach (var category in categories)
{
Console.WriteLine("Name : {0}, OccuranceCount {1}",category.Name, category.OccuranceCount);
}

Answer

You can use LINQ GroupBy combined with fancy Select overload with index, but since you need to update the entries anyway, IMO the best from time and space complexity would be to use a simple counting dictionary:

var counts = new Dictionary<string, int>();
foreach (var category in categories)
{
    int count;
    counts.TryGetValue(category.Name, out count);
    counts[category.Name] = category.OccuranceCount = ++count;
} 

For the record, here is the LINQ version:

foreach (var group in categories.GroupBy(c => c.Name))
    foreach (var item in group.Select((category, index) => new { category, index }))
        item.category.OccuranceCount = item.index + 1;
Comments