Reputation: 171
I want to be able to get the percentages of certain types of things in a list.
Say I have a list of Animals, but inside that list I have Cats, Dogs, And Snakes:
List<Animal> animals = new List<Animal>{
new Cat { Name="Cuddles", Sound=Sound.Meow, Age=3 },
new Dog { Name="Spot", Sound=Sound.Bark, Age=7 },
new Cat { Name="Karma", Sound=Sound.Meow, Age=10 },
new Snake { Name="Nagini", Sound=Sound.Hiss, Age=1 },
new Dog { Name="Sparky", Sound=Sound.Bark, Age=4},
new Cat { Name="Matty", Sound=Sound.Meow, Age=15}
};
And I want to be able to get the percentages of these animals, so a potential result set would be:
Cats: 0.50
Dogs: 0.35
Snakes: 0.15
But I'm not really sure how to get this type of result set. Especially if I just wanted to get the percentage of Cats.
I know I need to use list.OfType<Cat>()
to pull the list of just cats, but that's also when I'm having trouble getting the percentage of Cats, because I cant use .Sum() or .Average().
Any ideas?
Upvotes: 1
Views: 1028
Reputation: 1276
You are most of the way there
you can simply do:
var catPercent = list.OfType<Cat>().Count() / (float)list.Count();
Upvotes: 4
Reputation: 1500785
No, I don't think you need to be using OfType<>
at all. I suspect you really want GroupBy
:
var countsByType = animals.GroupBy(x => x.GetType(),
(t, g) => new { Type = t, Count = g.Count() });
That will give you:
{ Type = Cat, Count = 3 },
{ Type = Dog, Count = 2 },
{ Type = Snake, Count = 1 }
You can go from there to the proportion by dividing the count by the total if you want. For example:
var countsByType = animals.GroupBy(x => x.GetType(),
(t, g) => new { Type = t, Count = g.Count() })
.ToList();
// Could just use animals.Count, but this approach works for sequences
// which can only be enumerated once.
var totalCount = countsByType.Sum(t => t.Count);
var proportions = countsByType.Select(pair => new {
pair.Type,
Proportion = pair.Count / (double) totalCount
});
Upvotes: 8
Reputation: 4375
GroupBy is just what you need. It creates groups of items that have a common key, in your case the type of the class. Using a select on that grouping will allow you to create for instance a tuple that has the percentage you would like to get.
animals.GroupBy(a => a.GetType()).Select(group => new Tuple<Type, double>(group.Key, group.Count() / animals.Count()));
Upvotes: 1