首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >LINQ Fluent语法-取消数组中的项

LINQ Fluent语法-取消数组中的项
EN

Stack Overflow用户
提问于 2018-06-28 10:31:39
回答 4查看 387关注 0票数 0

我在为一个流利的LINQ查询而挣扎。我有一个带有Contributor数组的Product对象:

代码语言:javascript
运行
复制
public class Product
{
    public int Id {get;set;}
    public string Role {get;set;}
    public string Publisher {get;set;}
}
public class Contributor
{
    public string Id {get;set;}
    public string Name {get;set;}
    public Product[] ProductsContributedTo {get;set;}
}

我有一个Contributor集合,我希望过滤这些集合,以便:

  1. 我只选择在Contributor数组中存在作者角色记录的情况下的Contributor.ProductsContributedTo记录。
  2. 每个贡献者Contributor.ProductsContributedTo数组应该只包括作者角色。

以下是我迄今为止的尝试:

代码语言:javascript
运行
复制
 var authors = contributors.SelectMany(people => people.ProductsContributedTo
                                  .Where(product => product.Role == "Author")
                                  .Select(c => people))
                                  .ToList();

因此,通过选择正确的贡献者记录,这是可行的,但是如何过滤Contributor.ProductsContributedTo,使其只包含作者角色?

这是一个小提琴,证明我有3名贡献者记录巴里柯林斯,玛吉芬威克和塞奇威克福利。上面的LINQ查询只正确地选择了麦琪·芬威克和巴里·柯林斯,但是我如何过滤Contributor.ProductsContributedTo数组,使我只拥有他们各自的作者产品记录?

https://dotnetfiddle.net/hScdi4

编辑:

我对Fiddle做了一点小小的修改,因为每个Contributor都可以编写多个Product,所以我想说明这一点。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-06-28 10:45:33

这比你想象的要复杂得多:

代码语言:javascript
运行
复制
List<Contributor> authors = contributors
    .Where(x => x.ProductsContributedTo.Any(y => y.Role == "Author"))
    .Select(x => new Contributor { Id = x.Id, Name = x.Name, ProductsContributedTo = x.ProductsContributedTo.Where(y => y.Role == "Author").ToArray() })
    .ToList();

您必须将Contributor“克隆”到具有筛选的ProductsContributedTo列表的新Contributor中。

请注意,我为Role == "Author"过滤了两次,一次用于过滤Contributors,一次用于过滤所选Contributors的ProductsContributedTo

另一种方法是,无需重复检查Role,如下所示:

代码语言:javascript
运行
复制
List<Contributor> authors = contributors
    .Select(x => new { Contributor = x, FilteredProducts = x.ProductsContributedTo.Where(y => y.Role == "Author").ToArray() })
    .Where(x => x.FilteredProducts.Length != 0)
    .Select(x => new Contributor { Id = x.Contributor.Id, Name = x.Contributor.Name, ProductsContributedTo = x.FilteredProducts })
    .ToList();

我们将过滤后的ProductsContributedTo“保存”在一个匿名对象中,然后使用这个FilteredProducts来过滤Contributor。这或多或少相当于在基于关键字的linq中使用let关键字:

代码语言:javascript
运行
复制
List<Contributor> authors = (from x in contributors
                             let filteredProducts = x.ProductsContributedTo.Where(y => y.Role == "Author").ToArray()
                             where filteredProducts.Length != 0
                             select new Contributor { Id = x.Id, Name = x.Name, ProductsContributedTo = filteredProducts }
                            ).ToList();

请注意,通常您可以很好地使用分别包含Contributor及其筛选的Product的匿名对象,同时在Contributor中保留Product的完整列表:

代码语言:javascript
运行
复制
List<Contributor> authors = contributors
    .Select(x => new 
    { 
        Contributor = x, 
        FilteredProducts = x.ProductsContributedTo.Where(y => y.Role == "Author").ToArray() 
    })
    .Where(x => x.FilteredProducts.Length != 0)
    .ToList();
票数 2
EN

Stack Overflow用户

发布于 2018-06-28 10:42:58

下面的代码应该可以工作,它首先选择贡献者及其作者角色产品,然后只保留那些至少有一个产品的贡献者(以避免多次迭代产品集合):

代码语言:javascript
运行
复制
contributors.Select(contributor => 
    new Contributor()
    {
        Id = contributor.Id,
        Name = contributor.Name,
        ProductsContributedTo = contributor.ProductsContributedTo.Where(
            product => (product.Role == "Author")).ToArray()
    }).
    Where(contributor => (contributor.ProductsContributedTo.Length > 0));
票数 0
EN

Stack Overflow用户

发布于 2018-06-28 10:53:03

试着跟着。其他解决方案没有使用SelectMany。使用just添加一个额外的层,这是不必要的。:

代码语言:javascript
运行
复制
            var authors = contributors.SelectMany(people => people.ProductsContributedTo
                                 .Where(product => product.Role == "Author").Select(product => new { Id = product.Id, publisher = product.Publisher })
                                 .Select(c => new { contributorId = people.Id, name = people.Name, productId = c.Id, publisher = c.publisher }))
                                 .ToList();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51080652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档