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
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();
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; }
}
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);
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.
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.
101 LINQ Samples, namely Select - Anonymous Types 1
... select new { HomeTeam = fixture.HomeTeam, AwayTeam = fixture.AwayTeam };