如何编写一个LINQ查询来反转分层数据源的分组? [英] How do I write a LINQ query that inverts the grouping of a hierarchical data source?

查看:44
本文介绍了如何编写一个LINQ查询来反转分层数据源的分组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个人如何编写一个LINQ查询,该查询将获取分层的源数据并进行转换,从而使分组反向?

How would one write a LINQ query which takes a hierarchical source data and transforms it so that the grouping is inverted?

说我有一个主题对象列表,每个主题对象都包含一个标记集合,这些标记表示该主题上的元数据标记.我需要编写一个LINQ查询,以便从根本上翻转层次结构,这样我就有了一个标签列表,每个标签都包含用该特定标签标记的主题的集合.

Say I have a list of Topic objects each of which contains a collection of Tags which represent meta-data tags on that topic. What I need is to write a LINQ query to basically flip the hierarchy inside out so that I have a list of Tags each of which have a collection of topics that are tagged with that particular tag.

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" }

我希望上面的数据看起来像下面的结果.

I want the above data to look instead like the results below.

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 }

您可以假定任何重复的数据段都是参照唯一的,因为这是内存中的单个实例,并且这些重复的数据对同一对象只有几个引用.对于答案,使用匿名类来生成投影也是合理的,因为我意识到反转后类的形状可能会略有不同.

You can assume that any repeated piece of data is referentially unique in that that is a single instance in memory and these there are just several references to that same object. Also it is reasonable for the answer to use anonymous classes to produce the projection since I realize the shape of the classes may be slightly different after the inversion.

更新:我在下面添加了代码,以设置示例数据.我正在玩LinqPad中发布的答案和我自己的一些想法.

UPDATE: I added the code below which sets up the example data. I'm playing around with the answers posted and some of my own ideas in 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),
    },
};

推荐答案

在LinqPad中玩了一会儿之后,我认为我可能已经找到了合适的解决方案.

After playing around in LinqPad a bit I think I may have found a suitable solution.

这是简单的例子.

var topicsByTags = 
    from topic in topics
    from tag in topic.Tags
    group topic by tag;

为了摆脱每个主题下的多余标签"集合,我们可以执行以下操作.

And in order to get rid of the redundant Tags collection under each topic we can do the following.

var topicsByTags = 
    from topic in topics
    from tag in topic.Tags
    group new 
    {
        Title = topic.Title,
        Color = topic.Posted,
    } by tag into g
    select new
    {
        g.Key.Name,
        g.Key.Color,
        Topics = g,
    };

更新:以下是利用投影中的分组本身的另一种选择.上行是稍微干净的查询,下行是组Key会紧随该组,即使它不会被使用.

UPDATE: Below is another alternative which takes advantage of the grouping itself in the projection. Upside is slightly cleaner query, downside is that the group Key sticks around with the group even if it's not going to be used.

var topicsByTags = 
    from topic in topics
    from tag in topic.Tags
    group new 
    {
        Title = topic.Title,
        Color = topic.Posted,
    } by tag into g
    select new
    {
        g.Key.Name,
        g.Key.Color,
        Topics = g,
    };

我将拒绝接受自己的回答,以便就哪种解决方案可以解决我提出的最佳问题进行辩论.

I'll hold off accepting my own answer to allow some debate over which solution solves the problem that I posed the best.

这篇关于如何编写一个LINQ查询来反转分层数据源的分组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆