繁体   English   中英

LINQ with subselect和groupby只获取列表中每个项目的最新版本

[英]LINQ with subselect and groupby to get only the latest version of each item in a list

对于LINQ来说,我是新手......

我有一个IEnumerable通用列表,其中包含不同版本的答案(每个版本都有一个问题的FK)。 从这个列表中我只需要获得最新版本答案的字典。

一个非常简化的类图:


-ID
-题
- ......其他财产

回答
-ID
-版
-QuestionID
-值
- ......其他财产

目前我有以下内容:

IEnumerable<Answer> answers = GetAnswers();

IDictionary<long, AnswerDTO> latestVersionAnswers = new Dictionary<long, AnswerDTO>();
if (answers != null)
{
latestVersionAnswers = answers
      .OrderBy(e => e.ID)
      .GroupBy(e => e.Question.ID)
      .Select(g => new AnswerDTO
                        {
                             Version = g.Last().Version, // g.Select(e => e.Version).Max(), 
                             QuestionID = g.Key,
                             ID = g.Last().ID,
                             Value = g.Last().Value
                                 }).ToDictionary(c => c.QuestionID);
        }

虽然这在很大程度上起作用,但您可以很快发现它需要一些严肃的优化(并且有点脆弱,因为它取决于答案记录行顺序而不是“最大”逻辑)。 使用LINQ执行此操作的最佳方法是什么,或者最好只为每个循环执行多个操作?

  1. 如果我只需要版本(而不是ID,Value等)我就不需要OrderBy,因为我可以去g.Select(e => e.Version).Max()(或者我现在看到C#List <> GroupBy 2值的帖子,但这又会返回key / s和一个属性:Version)。
  2. 最终,在这种特殊情况下,我更愿意“过滤”原始列表并返回原始答案项而不是涉及AnswerDTO。

任何指针或帮助将不胜感激!

怎么样......

   private void button1_Click(object sender, EventArgs e)
    {
      List<Answer> list = GetAnswers();

      var dict = (from a in list
                 group a by a.QuestionID into grp
                 from g in grp
                 where g.Version == grp.Max(m => m.Version)
                 select new { id = g.QuestionID, q = g }).ToDictionary( o => o.id, o => o.q);

      StringBuilder sb = new StringBuilder();
      foreach (var elem in dict)
      {
        sb.AppendLine(elem.Key.ToString() + "-" + elem.Value.Version.ToString());
      }
      MessageBox.Show(sb.ToString());
    }

    private List<Answer> GetAnswers()
    {
      List<Answer> result = new List<Answer>();
      result.Add(new Answer() { ID = 1, QuestionID = 1, Version = 1 });
      result.Add(new Answer() { ID = 2, QuestionID = 1, Version = 2 });
      result.Add(new Answer() { ID = 3, QuestionID = 1, Version = 3 });
      result.Add(new Answer() { ID = 4, QuestionID = 2, Version = 1 });
      result.Add(new Answer() { ID = 5, QuestionID = 2, Version = 2 });
      result.Add(new Answer() { ID = 6, QuestionID = 2, Version = 3 });
      result.Add(new Answer() { ID = 7, QuestionID = 3, Version = 1 });
      result.Add(new Answer() { ID = 8, QuestionID = 3, Version = 2 });
      result.Add(new Answer() { ID = 9, QuestionID = 3, Version = 3 });
      result.Add(new Answer() { ID = 10, QuestionID = 3, Version = 4 });
      return result;
    }
latestVersionAnswers = answers
  .GroupBy(e => e.Question.ID)
  .Select(g => g.OrderByDescending(e => e.Version).First())
  .ToDictionary(e => e.Question.ID);

或者,如果您更喜欢选择ToDictionary的重载:

latestVersionAnswers = answers
  .GroupBy(e => e.Question.ID)
  .ToDictionary(
    g => g.Key,
    g => g.OrderByDescending(e => e.Version).First()
  );

我只想重写数据模型以包含当前答案版本ID。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM