Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialDaniel Breen
14,943 PointsSelect vs SelectMany When Getting Average
With the following code in mind...
var sightingsCorrect = birds.SelectMany(b => b.Sightings).Count(); // 1817
var sightingsWrong = birds.Select(b => b.Sightings).Count(); // 201
var average = birds.Select(b => b.Sightings.Count()).Average(); // 9.03980099502488
Note that sightingsCorrect
uses SelectMany(), while sightingsWrong
and average use Select().
Why don't we use SelectMany to get the average? How does Linq bring back the correct average? I would assume that average
would be 1 (201 / 201 = 1)
1 Answer
Steven Parker
231,248 PointsThese variable names are a bit confusing, "sightingsCorrect" is actually the total number of sightings, and "sightingsWrong " is just a count of birds. It could be written more simply without the "Select" as:
var sightingsWrong = birds.Count(); // 201
The reason the average works is that the "Count" is applied to the sightings for each bird. So the "Average" totals them up and then divides by the number of counts. You can't use "SelectMany" there because it works on lists, not individual values as the "Count" returns.
Daniel Breen
14,943 PointsDaniel Breen
14,943 Pointsvar sightingsWrong = birds.Select(b => b.Sightings).Count();
is actually not a count of birds. It's a count of unflattenedSightings
lists, which happens to be equal to the count of birds. That's what I've been trying to figure out. :) I don't understand howbirds.Select(b => b.Sightings.Count()).Average();
is expanding (unflattening?)Sightings
without using SelectMany to count each item in Sightings before averaging.Steven Parker
231,248 PointsSteven Parker
231,248 PointsWhen I said "count of birds", I meant that it "happens to be equal to the count of birds". So it makes sense to use the simpler method and just count birds since you get the same result.
The reason you don't need (and can't use) "SelectMany" with "Average" is because "
b.Sightings.Count()
" converts each list into a single number, eliminating the need for "flattening". Then those single numbers get averaged.You _can_use flattening to compute an average, and that is also shown in the video, but you do the math yourself instead of using the "Average" method:
var averageSightings = birds.SelectMany(b => b.Sightings).Count() / birds.Count(); // 9