LINQ GroupBy List<>
本文关键字:gt GroupBy lt LINQ List | 更新日期: 2023-09-27 18:26:19
我有一个简单的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;
}
}
如果您知道这是不可能的,那么可以删除一些针对空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()
});