Reputation: 315
I'm using a linq query which looks (after some simplification) something like the following:
List<UserExams> listUserExams = GetUserExams();
var examData =
from userExam in listUserExams
group by userExam.ExamID into groupExams
select new ExamData()
{
ExamID = groupExams.Key,
AverageGrade = groupExams.Average(e => e.Grade),
PassedUsersNum = groupExams.Count(e => /* Some long and complicated calculation */),
CompletionRate = 100 * groupExams.Count(e => /* The same long and complicated calculation */) / TotalUsersNum
};
What bothers me is the calculation expression which appears twice, for PassedUsersNum and CompletionRate.
Assuming that CompletionRate = (PassedUsersNum / TotalUsersNum) * 100
, how can I write it by reusing the calculation of PassedUsersNum, instead of writing that expression again?
Upvotes: 4
Views: 1040
Reputation: 36339
You can also just extract your Count func into another method which returns a Func if you want, or a method that takes a double and returns a bool.
List<UserExams> listUserExams = GetUserExams();
var examData =
from userExam in listUserExams
group by userExam.ExamID into groupExams
select new ExamData()
{
ExamID = groupExams.Key,
AverageGrade = groupExams.Average(funcMethod()),
PassedUsersNum = groupExams.Count(e => traditionalMethod(e)),
CompletionRate = 100 * groupExams.Count(e => /* The same long and complicated calculation */) / TotalUsersNum
};
// later...
private Func<double,bool> funcMethod(){ return e=> /* your calculation */ }
private bool traditionalMethod(double d){ return /* your calculation */ }
Upvotes: 1
Reputation: 1502106
The simplest way would be to use let
to inject another selection step first:
List<UserExams> listUserExams = GetUserExams();
var examData =
from userExam in listUserExams
group by userExam.ExamID into groupExams
let passCount = groupExams.Count( /* long expression */)
select new ExamData()
{
ExamID = groupExams.Key,
AverageGrade = groupExams.Average(e => e.Grade),
PassedUsersNum = passCount,
CompletionRate = 100 * passCount / TotalUsersNum
};
The expression will only be evaluated once per group, of course.
Upvotes: 6