【问题标题】:Object initializers in a LINQ query - is it possible to reuse calculated data?LINQ 查询中的对象初始化器 - 是否可以重用计算数据?
【发布时间】:2011-09-13 23:39:24
【问题描述】:

我正在使用一个 linq 查询,它看起来(经过一些简化)类似于以下内容:

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
};

困扰我的是计算表达式出现了两次,分别是 PassedUsersNum 和 CompletionRate。

假设CompletionRate = (PassedUsersNum / TotalUsersNum) * 100,如何通过重用PassedUsersNum的计算来编写它,而不是再次编写那个表达式?

【问题讨论】:

    标签: c# linq object-initializers


    【解决方案1】:

    最简单的方法是先使用let 注入另一个选择步骤:

    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
        };
    

    当然,每个组只计算一次表达式。

    【讨论】:

      【解决方案2】:

      您也可以将您的 Count func 提取到另一个返回 Func 的方法中(如果需要),或者采用 double 并返回 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 */ }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-14
        • 2012-03-01
        • 2010-09-24
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多