Solución:
101 ejemplos de LINQ, a saber, Seleccionar – Tipos anónimos 1
... select new { HomeTeam = fixture.HomeTeam, AwayTeam = fixture.AwayTeam };
Lo siguiente devolverá un IEnumerable
IEnumerable<Team> drew =
from fixture in fixtures
where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
from team in new[]{fixture.HomeTeam, fixture.AwayTeam}
select team;
O, con el estilo fluido de LINQ:
IEnumerable<Team> drew =
fixtures
.Where(fxtr => fxtr.Played && (fxtr.HomeScore == fxtr.AwayScore))
.SelectMany(fixture => new[]{fixture.HomeTeam, fixture.AwayTeam});
Aplanamiento y FlatMap
Este requisito a menudo se denomina “aplanamiento”. Es decir, tomando un
SelectMany
ambos mapas (un elemento fijo en una matriz de equipos) y aplanados (una secuencia de matrices de equipos en una secuencia de equipos). Es similar a la función “flatMap” en otros lenguajes como Java y JavaScript.
Es posible separar el mapeo y el aplanamiento:
IEnumerable<Team> drew =
fixtures
.Where(fxtr => fxtr.Played && (fxtr.HomeScore == fxtr.AwayScore))
// map
.Select(fixture => new[]{fixture.HomeTeam, fixture.AwayTeam})
// flatten
.SelectMany(teams => teams);
Otros enfoques
Bloque de iterador
Se puede lograr lo mismo con un bloque de iterador, pero sospecho que este rara vez es el mejor enfoque:
IEnumerable<Team> Drew(IEnumerable<Fixture> fixtures){
var draws =
fixtures
.Where(fxtr => fxtr.Played && (fxtr.HomeScore == fxtr.AwayScore));
foreach(var fixture in draws){
yield return fixture.HomeTeam;
yield return fixture.AwayTeam;
}
}
Unión
La unión también es una opción, pero tiene el potencial de producir resultados diferentes a los anteriores:
-
El orden de los resultados será diferente. Todos los resultados de Casa se devuelven y luego todos los resultados de Visitante.
-
Union
enumera los dispositivos dos veces, por lo que, dependiendo de cómo se implementen los dispositivos, existe la posibilidad de que los dispositivos se actualicen entre llamadas. Por ejemplo, si se agrega un nuevo partido empatado entre llamadas, entonces el equipo visitante podría ser devuelto pero no el equipo local.
Como describe Mike Powell:
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 );
Dependiendo de cómo se obtienen / implementan los accesorios, puede valer la pena considerar ‘almacenar en caché’ los accesorios dibujados para evitar tener que enumerarlos dos veces.
var draws =
( from fixture in fixtures
where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
select fixture
).ToList();
IEnumerable<Team> drew =
(from draw in draws select draw.HomeTeam)
.Union(from draw in draws select draw.AwayTeam);
O usando el estilo fluido:
var draws =
fixtures
.Where(fxtr => fxtr.Played && (fxtr.HomeScore == fxtr.AwayScore))
.ToList();
IEnumerable<Team> drew =
draws.Select(fixture => fixture.HomeTeam)
.Union(draws.Select(fixture => fixture.AwayTeam));
Modificando la clase de Aparato
Se podría considerar agregar “ParticipatingTeams” a la clase Fixture para obtener:
IEnumerable<Team> drew =
from fixture in fixtures
where fixture.Played && (fixture.HomeScore == fixture.AwayScore)
from team in fixture.ParticipatingTeams
select team;
pero como @MattDeKrey señala, eso requiere un cambio de contrato.
Muestras de código
Las muestras de código están disponibles en Repl.it
Creo que está buscando el método Union de la siguiente manera:
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);