Como escrevo uma consulta LINQ que inverte o agrupamento de uma fonte de dados hierárquica?
Como alguém escreveria uma consulta LINQ que usa dados de origem hierárquicos e os transforma para que o agrupamento seja invertido?
Digamos que eu tenha uma lista de objetos Topic, cada um contendo uma coleção de Tags que representam tags de metadados nesse tópico. O que eu preciso é escrever uma consulta LINQ para basicamente inverter a hierarquia de modo que eu tenha uma lista de Tags, cada uma com uma coleção de tópicos marcados com aquela tag em particular.
Topic { Title = "Political Debate #1", Posted = 01/02/2008 }
Tag { Name = "Contraversial", Color = "Red" }
Tag { Name = "Politics", Color = "LightBlue" }
Topic { Title = "iPhone to support SiliverLight!", Posted = 02/23/2009 }
Tag { Name = "BleedingEdge", Color = "LightBlue" }
Tag { Name = "Contraversial", Color = "Red" }
Tag { Name = ".NET", Color = "LightGreen" }
Topic { Title = "Fed Chairman admits guilt for causing second Great Depression", Posted = 06/15/2010 }
Tag { Name = "Politics", Color = "LightBlue" }
Tag { Name = "Contraversial", Color = "Red" }
Quero que os dados acima sejam semelhantes aos resultados abaixo.
Tag { Name = "Contraversial", Color = "Red" }
Topic { Title = "Political Debate #1", Posted = 01/02/2008 }
Topic { Title = "iPhone to support SiliverLight!", Posted = 23/02/2009 }
Topic { Title = "Fed Chairman admits guilt for causing second Great Depression", Posted = 06/15/2010 }
Tag { Name = "Politics", Color = "LightBlue" }
Topic { Title = "Political Debate #1", Posted = 01/02/2008 }
Topic { Title = "Fed Chairman admits guilt for causing second Great Depression", Posted = 06/15/2010 }
Tag { Name = ".NET", Color = "LightGreen" }
Topic { Title = "iPhone to support SiliverLight!", Posted = 23/02/2009 }
Você pode supor que qualquer dado repetido é referencialmente único, pois há uma única instância na memória e há apenas várias referências ao mesmo objeto. Também é razoável que a resposta use classes anônimas para produzir a projeção, pois percebo que a forma das classes pode ser ligeiramente diferente após a inversão.
UPDATE: eu adicionei o código abaixo que configura os dados de exemplo. Estou brincando com as respostas postadas e algumas das minhas próprias ideias no LinqPad.
var tags = new[]
{
new { Name = "Contraversial", Color = "Red" },
new { Name = "Politics", Color = "LightBlue" },
new { Name = ".NET", Color = "LightGreen" },
new { Name = "BleedingEdge", Color = "LightBlue" }
};
var topics = new[]
{
new
{
Title = "Political Debate #1",
Posted = DateTime.Parse("01/02/2008"),
Tags = (from t in tags where new []{"Contraversial", "Politics"}.Contains(t.Name) select t),
},
new
{
Title = "iPhone to support SiliverLight!",
Posted = DateTime.Parse("02/23/2009"),
Tags = (from t in tags where new []{"BleedingEdge", "Contraversial", ".NET", }.Contains(t.Name) select t),
},
new
{
Title = "Fed Chairman admits guilt for causing second Great Depression",
Posted = DateTime.Parse("06/15/2010"),
Tags = (from t in tags where new []{"Contraversial", "Politics"}.Contains(t.Name) select t),
},
};