Linq 过滤器避免循环

Posted

技术标签:

【中文标题】Linq 过滤器避免循环【英文标题】:Linq filter to avoid a loop 【发布时间】:2019-07-20 21:31:52 【问题描述】:

我正在尝试制定一个 LINQ 查询,但不是专业人士,所以无论我尝试什么都行不通。我想过滤列表以从下面的列表中获取电子邮件 ID,其中分数为 0,按团队名称分组。

我尝试这样做的方式是:

    获取不同团队名称的列表。 遍历每个不同的团队名称并获取得分为 0 的电子邮件 ID。
Team    Name   Score    EmailId  
Hawk    Amy     0       Amy@gmail.com  
Hawk    Aby     0       Aby@gmail.com  
Hawk    Raf     1       Raf@gmail.com  
Hawk    Jay     2       Jay@gmail.com  
Eagle   Blu     0       Blu@gmail.com  
Eagle   Tru     1       Tru@gmail.com  

我想得到两行:HawkAmy@gmail.com, Aby@gmail.com,下一个结果将是 EagleBlue@gmail.com这可以通过 LINQ 一步完成吗?

【问题讨论】:

data.Where(x => x.Score == 0).Select(x => new x.Team, x.EmailId ).GroupBy(x => x.Team)? 为什么要避免循环? 为什么要按团队分组?您最多将获得 2 条记录:Hawk、Eagle。这就是你想要的吗? “想要过滤列表以获取按团队名称分组的分数为 0 的电子邮件 ID。”实际上 linq 太酷了,它甚至把函数命名为普通人说话;)Where 和GroupBy。在您的情况下, get 被称为 Select 您的第一种方法可能非常易读且易于维护 :) 但我可以理解使用漂亮 linq 语句的冲动;) 【参考方案1】:

不确定你目前在做什么,但我会这样做

var result = list.Where(p => p.Score == 0)
                 .Select(p => newp.Team, p.EmailId)
                 .GroupBy(p => p.Team)
                 .Distinct();

【讨论】:

【参考方案2】:

想要过滤列表以获取按团队名称分组的分数为 0 的电子邮件 ID。

过滤列表以获取得分为 0 的电子邮件 ID

var filteredList = list.Where(record => records.Score == 0);

按团队名称分组

var groupedByTeamName = filteredList.GroupBy(record => record.Team)

如果我没记错的话,这将返回一个IEnumerable<IGrouping<TRecord, TTeam>>IGrouping<T,K> 只是一个带有 Key 属性的列表,其中包含您分组的内容(在这种情况下为团队)。

您当然可以以级联方式调用它们:

list.Where(record => records.Score == 0).GroupBy(record => record.Team);

但调试会有点困难,因为您必须选择代码并快速查看句子的各个部分。有时这不起作用。

【讨论】:

【参考方案3】:

想要过滤列表以获取按团队名称分组的分数为 0 的电子邮件 ID。

这是不是很难说:

我想要所有没有得分的团队成员的电子邮件?

将您的数据分组为“球队及其球员及其得分”;只保留分数为零的球队,并提取球员的电子邮件。

为此,我们使用overload of GroupBy with aKeySelector and aResultSelector

var emailsOfPlayersInTeamsWithZeroScor = myInput.GroupBy

    // keySelector: the team
    .GroupBy(inputItem => inputItem.Team,

    // ResultSelector: from every Team with its players and scores
    // make sequences of emails of players and check if there is a score at all
    (team, players) => new
    
        // not interested in the team

        // remember if all scores are zero
        HasOnlyZeroScore = players.All(player.Score == 0),

        // remember all emails of the players in the team
        PlayerEmails = players.Select(player => player.Email),
    )

    // keep only the items with a zero score
    .Where(team => team.HasOnlyZeroScore)

    // and select the lists of emails per team as one big list:
    .SelectMany(team => team.PlayerEmails);

简单的祝你好运!

【讨论】:

以上是关于Linq 过滤器避免循环的主要内容,如果未能解决你的问题,请参考以下文章

如何使用linq c#优化嵌套循环并从另一个列表中过滤

使用 Linq 表达式进行 C# 动态数据库过滤

是否有使用 Linq 动态创建过滤器的模式?

返回唯一值并避免遍历未过滤的范围

LINQ查询中的C#多个OR条件[重复]

通过在 Spark 中列出该位置下的文件来避免“for 循环”