带有GroupBy的Linq表达式

本文关键字:表达式 Linq GroupBy 带有 | 更新日期: 2023-09-27 18:25:28

我有一个linq表达式,我想将其分组并转换为硬类型List<DocumentGroup>

此linq查询工作正常:

var DocumentGroups = (from dt in DocumentTypes
                       let dg = dt.DocumentGroup
                       select new DocumentGroup(){
                           Name = dg.Namn, 
                           Id = dg.Id
                        }).GroupBy(group => group.Id).ToList(); 

现在我想做同样的查询并将其转换为List<DocumentGroup>,但我收到了以下错误:

无法将"Grouping[System.Guid,ConsoleApplication1+DocumentGroup]"类型的对象强制转换为"DocumentGroup"类型。

List<DocumentGroup> DocumentGroups = (from dt in DocumentTypes
                           let dg = dt.DocumentGroup
                           select new DocumentGroup(){
                               Name = dg.Namn,
                               Id = dg.Id
                           }).GroupBy(group => group.Id).Cast<DocumentGroup>.ToList(); 

如果我从linq表达式中删除.GroupBy(group => group.Id),它可以正常工作,但我需要组表达式来过滤掉它。我怎样才能做到这一点?

DocumentGroup类

public class DocumentGroup
{
    public string Name { get; set; }
    public Guid Id { get; set; }
}

带有GroupBy的Linq表达式

当您使用GroupBy时,您会得到组。因此,将一个组投射到单个项目将失败。

如果你只想删除重复项,那么你可以从每组中选择第一个项目:

var DocumentGroups = (from dt in DocumentTypes
                      let dg = dt.DocumentGroup
                      select new DocumentGroup() 
                             { 
                                Name = dg.Namn, 
                                Id = dg.Id 
                             }).GroupBy(group => group.Id)
                               .Select(g => g.First())
                               .ToList();

在执行GroupBy之前,您有一个DocumentGroup(类似于一维数组)列表

1    Name1       <record 1 of DocumentGroup>
1    Name2       <record 2 of DocumentGroup>
1    Name3       <record 3 of DocumentGroup>
2    Name4       <record 4 of DocumentGroup>
3    Name5       <record 5 of DocumentGroup>

完成GroupBy后,您将获得IGrouping<int, DocumentGroup>(类似于二维阵列)的列表

1    1    Name1       --|
     1    Name2         -- <record 1 of IGrouping<int, DocumentGroup>
     1    Name3       --|
2    2    Name4            <record 2 of IGrouping<int, DocumentGroup>>
3    3    Name5            <record 3 of IGrouping<int, DocumentGroup>>

因此,要获得DocumentGroup,您需要首先从Grouping项目访问,然后获得DocumentGroup,例如:

var groupOfDocumentGroups = /* omitted code */
     select new DocumentGroup() { Name = dg.Namn, Id = dg.Id })
     .GroupBy(group => group.Id)
     .ToList();
foreach(var groupItem in groupOfDocumentGroups)
{
    // groupItem type is IGrouping<int, DocumentGroup>
    // groupItem has `Key` property which is an integer of the Id.
    // groupItem is also a collection that you can do enumeration.
    foreach(var item in groupItem)
    {
        // there you go, item type is DocumentGroup
    }
}

但我必须有组表达式才能过滤掉

我假设您想在所有DocumentType中获得所有唯一的DocumentGroup,那么Salman22的答案就是您想要的。

在这种情况下,您也可以使用Distinct。如果您正在使用linq-to实体,您可以只使用。

var documentGroups = context.DocumentTypes
    .Select(x => x.DocumentGroup)
    .Distinct()
    .ToList();

如果您使用linq来处理对象,那么可以先实现IEqualityComparer<DocumentGroup>

class DocumentGroupComparer : IEqualityComparer<DocumentGroup>
{
    public bool Equals(DocumentGroupx, DocumentGroupy)
    {
        return x.Id == y.Id;
    }
    public int GetHashCode(DocumentGroup obj)
    {
        return obj.Id.GetHashCode();
    }
}
var documentGroups = DocumentTypes
    .Select(x => x.DocumentGroup)
    .Distinct(new DocumentGroupComparer())
    .ToList();