Can I select multiple objects in a Linq query

后端 未结 7 435
有刺的猬
有刺的猬 2021-02-02 06:48

Can I return more than one item in a select? For instance I have a List of Fixtures (think football (or soccer for the yanks) fixtures). Each fixture contains a home and away t

相关标签:
7条回答
  • 2021-02-02 07:22

    Taking a stab at this myself I came up with the same version as 'it depends'.

    Using query comprehension syntax:

    IEnumerable<Team> drew =
        from fixture in fixtures
        where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
        from team in new[]{fixture.AwayTeam, fixture.HomeTeam}
        select team;
    

    Using lambda with extension methods:

    IEnumerable<Team> drew =
        fixtures.Where(f => f.Played && f.HomeScore == f.AwayScore)
        .SelectMany(f => new[]{f.HomeTeam, f.AwayTeam});
    

    Edit: I don't know if a team could have possibly played and drawn more than once in your database, but if that's possible, then you might want to make use of the Distinct query operator:

    IEnumerable<Team> drew =
        (from fixture in fixtures
         where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
         from team in new[]{fixture.AwayTeam, fixture.HomeTeam}
         select team).Distinct();
    

    or:

    IEnumerable<Team> drew =
        fixtures.Where(f => f.Played && f.HomeScore == f.AwayScore)
        .SelectMany(f => new[]{f.HomeTeam, f.AwayTeam})
        .Distinct();
    
    0 讨论(0)
  • 2021-02-02 07:23

    Or you can define a type to hold all that data:

    IEnumerable<TeamCluster> drew = from fixture in fixtures
                             where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
                             select new TeamCluster {
                                 Team1 = fixture.HomeTeam,
                                 Team2 = fixture.AwayTeam,
                                 Score1 = fixture.HomeScore,
                                 Score2 = fixture.AwayScore
                             };
    
    class TeamCluster {
        public Team Team1 { get; set; }
        public Team Team2 { get; set; }
        public int Score1 { get; set; }
        public int Score2 { get; set; }
    }
    
    0 讨论(0)
  • 2021-02-02 07:29

    I think you're looking for the Union method as follows:

    IEnumerable<Team> drew = (from fixture in fixtures
                         where fixture.Played 
                            && (fixture.HomeScore == fixture.AwayScore)
                         select fixture.HomeTeam)
                         .Union(from fixture in fixtures
                         where fixture.Played 
                            && (fixture.HomeScore == fixture.AwayScore)
                         select fixture.AwayTeam);
    
    0 讨论(0)
  • 2021-02-02 07:37

    I came up against this very issue, and couldn't find what I wanted so I wrote a small extension method which did what I wanted.

    public static IEnumerable<R> MapCombine<M, R>(this IEnumerable<M> origList, params Func<M, R>[] maps)
    {
        foreach (var item in origList)
        foreach (var map in maps)
        {
            yield return map(item);
        }
    }
    

    Following the problem in the question, you would then do something like this

    var drew = fixtures.Where(fixture => fixture.Played && 
                            (fixture.HomeScore == fixture.AwayScore))
                        .MapCombine(f => f.HomeTeam, f => f.AwayTeam);
    

    Interestingly intellisense isn't exactly happy about this, you don't get the lamdba expression in the top of the drop down, however after the '=>' its quite happy. But the main thing is the compiler is happy.

    0 讨论(0)
  • 2021-02-02 07:41

    Edit: Sorry, misunderstood your original question, so rewrote answer.

    You could use the "SelectMany" operator to do what you want:

    IEnumerable<Team> drew =
               (from fixture in fixtures
                where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
                      select new List<Team>()
                                 { HomeTeam = fixture.HomeTeam,
                                   AwayTeam = fixture.AwayTeam
                                 }).SelectMany(team => team);
    

    This will return a flattened list of teams that drew.

    0 讨论(0)
  • 2021-02-02 07:45

    101 LINQ Samples, namely Select - Anonymous Types 1

    ... select new { HomeTeam = fixture.HomeTeam, AwayTeam = fixture.AwayTeam };
    
    0 讨论(0)
提交回复
热议问题