繁体   English   中英

LINQ Group通过列表<>

[英]LINQ GroupBy List<>

我有一个简单的LINQ查询,它试图执行GroupBy,其中语句中的一项是List<string>.

var viewModel = reports
       .GroupBy(c => new { c.Id, c.PetList })
       .Select(g => new ArmReportModel
        {
            PetList = g.Key.PetList,
            Pets = g.Count()
        });

在此语句之前,我正在执行我的EF存储库方法,该方法最终将调用一个方法来创建上述PetList。

如果我从GroupBy()删除PetList,它会按预期工作。 为了按List<string>类型分组,我必须做些什么吗?

我假设Id是一个标识符,因此具有相同Id任何两个c实际上都是相同的,并且具有相同的PetList 因此,我们可以GroupBy只是Id ,并获得PetList另一种方式:

var viewModel = reports
  .GroupBy(c => c.Id)
  .Select(g => new ArmReportModel
  {
    PetList = g.First().PetList, // Might need FirstOrDefault() with some providers
    Pets = g.Count()
  });

除此以外,我首先要确保可以将IEqualityComparer<T>GroupBy 如果提供者允许的话,那就没问题了。 否则,我将从以下内容开始:

reports.Select(c => new {c.Id, c.PetList}).AsEnumerable()

这会将提供程序所需的最小值检索到内存中,以便从那时起可以使用linq-to-objects提供程序。

我需要能够为某些T定义IEqualityComparer<T> ,所以我停止使用匿名类型:

private class IdAndList
{
  public int Id { get; set; }
  public List<string> PetList { get; set; }
}

private class ReportIdAndPetListComparer : IEqualityComparer<IdAndList>
{
  public bool Equals(IdAndList x, IdAndList y)
  {
    if (ReferenceEquals(x, y)) return true;
    if (x == null || y == null) return false;
    if (x.Id != y.Id) return false;
    if (x.PetList == null) return y.PetList == null;
    if (y.PetList == null) return false;
    int count = x.PetList.Count;
    if (y.PetList.Count != count) return false;
    for (int i = 0; i != count; ++i)
      if (x.PetList[i] != y.PetList[i]) return false;
    return true;
  }

  public int GetHashCode(IdAndList obj)
  {
    int hash = obj.Id;
    if (obj.PetList != null)
      foreach (string pet in obj.PetList)
        hash = hash * 31 + pet.GetHashCode();
    return hash;
  }
}

如果您知道不可能,则可以删除某些针对null PetList的测试。

现在:

var viewModel = reports.Select(c => new IdAndList{c.Id, c.PetList}).AsEnumerable()
    .GroupBy(c => c, new ReportIdAndPetListComparer())
    .Select(g => new ArmReportModel
    {
        PetList = g.Key.PetList,
        Pets = g.Count()
    });

或者,如果提供程序无法处理构造IdAndPetList类型,则:

var viewModel = reports.Select(c => new {c.Id, c.PetList})
    .AsEnumerable()
    .Select(c => new IdAndList{c.Id, c.PetList})
    .GroupBy(c => c, new ReportIdAndPetListComparer())
    .Select(g => new ArmReportModel
    {
        PetList = g.Key.PetList,
        Pets = g.Count()
    });

暂无
暂无

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

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