user1630575
user1630575

Reputation: 171

Linq filter to avoid a loop

I am trying to formulate a LINQ query but not a pro at it so whatever I try is not working. I would like to filter the list to get email-ids from below list where score is 0 grouped by the Team Name.

The way I was trying to do it was:

  1. Get list of distinct Team Names.
  2. Loop through each distinct team name and get the email-ids where score is 0.
Team    Name   Score    EmailId  
Hawk    Amy     0       [email protected]  
Hawk    Aby     0       [email protected]  
Hawk    Raf     1       [email protected]  
Hawk    Jay     2       [email protected]  
Eagle   Blu     0       [email protected]  
Eagle   Tru     1       [email protected]  

I would like to get two lines: Hawk and [email protected], [email protected] and the next result would be Eagle with [email protected]. Is this possible through LINQ and in a single step?

Upvotes: 1

Views: 638

Answers (3)

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

Want to filter the list to get email-ids where score is 0 grouped by the Team Name.

Is this a difficult way to say:

I want all emails of team-members that are in teams that didn't score?

Group your data into "Teams with their players and their scores"; Keep only those teams that have only zero scores and extract the emails from the players.

For this we use the 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);

Simple comme bonjour!

Upvotes: 1

Pablo Recalde
Pablo Recalde

Reputation: 3571

Want to filter the list to get email-ids where score is 0 grouped by the Team Name.

filter the list to get email-ids where score is 0

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

grouped by the Team Name

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

this will return an IEnumerable<IGrouping<TRecord, TTeam>> if I'm not mistaken. IGrouping<T,K> is just a list with a Key property holding what you grouped by (a Team in this case).

you can of course call them in cascade-style:

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

but debugging will be a little harder as you will have to select the code and quick watch parts of the sentence. And there are times this doesn't work.

Upvotes: 3

Matti
Matti

Reputation: 391

Not sure what you're currently doing, but this is how I would do it

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

Upvotes: 3

Related Questions