Reputation: 175
I want to optimize this code for counting the number of occurrences in a list of strings. To be specific, I have two lists
1) cat
: a huge list of string with duplicates (duplicates must exist).
2) cat_unq
: the distinct elements from cat.
What I am currently doing in my code is looping all unique elements in cat_unq
and counting how many times the unique element exists in the list of duplicates. The search runs on a mobile device.
I already tried switching to arrays from list but the performance was slightly better and not sufficient.
Another try was using parallel search using foreach parallel but the performance was not stable.
Here is the code I am currently using :
private List<int> GetCategoryCount(List<string> cat, List<string> cat_unq)
{
List<int> cat_count = new List<int>();
for (int i = 0; i < cat_unq.Count; i++)
cat_count.Add(cat.Where(x => x.Equals(cat_unq[i])).Count());
return cat_count;
}
Upvotes: 3
Views: 417
Reputation: 136104
It is slow because you are searching the entire cat
array for every unique name. (cat.Where(....).Count()
).
Instead, group your cat list with duplicates, and make it a dictionary. Then you can quickly find the number of each unique name.
private List<int> GetCategoryCount(List<string> cat, List<string> cat_unq)
{
var catsDict = cat.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
return cat_unq.Select(c => catsDict[c]).ToList();
}
Note that if you are elsewhere forming your uniqe list of cat names its pointless, you can do that all together in the above (The dictionary has the unique cat names as keys)
// No need for a separate list of unique names
private List<int> GetCategoryCount(List<string> cat)
{
return cat.GroupBy(x => x).Select(g => g.Count()).ToList();
}
or maybe what you actually wanted was a list back of all the unique names and the counts
// No need for a separate list of unique names - as this one returns it with the counts in a dictionary
private Dictionary<string,int> GetCategoryCount(List<string> cat)
{
return cat.GroupBy(x => x).ToDictionary((k => k.Key, v => v.Count());
}
Upvotes: 5