使用Linq反转层次结构

时间:2015-02-18 04:51:03

标签: c# linq linq-to-objects

鉴于课程

public class Article
{
    public string Title { get; set; }
    public List<string> Tags { get; set; }
}

List<Article> articles;

如何使用Linq从单个标签(可能与一篇或多篇文章相关联)创建“地图”?

Dictionary<string, List<Article>> articlesPerTag;

我知道我可以选择所有这样的标签

var allTags = articlesPerTag.SelectMany(a => a.Tags);

但是,我不确定如何将每个选定的标签与其起源的文章相关联。

我知道我可以按照

的方式写这个
Dictionary<string, List<Article>> map = new Dictionary<string, List<Article>>();
foreach (var a in articles)
{
    foreach (var t in a.Tags)
    {
        List<Article> articlesForTag;
        bool found = map.TryGetValue(t, out articlesForTag);
        if (found)
            articlesForTag.Add(a);
        else
            map.Add(t, new List<Article>() { a });
    }
}

但我想了解如何使用Linq来实现这一目标。

2 个答案:

答案 0 :(得分:3)

如果您特别需要它作为从标签到文章的字典,您可以使用类似的东西。

var map = articles.SelectMany(a => a.Tags.Select(t => new { t, a }))
    .GroupBy(x => x.t, x => x.a)
    .ToDictionary(g => g.Key, g => g.ToList());

虽然使用查找会更有效,但这正是您尝试构建的内容。

var lookup = articles.SelectMany(a => a.Tags.Select(t => new { t, a }))
    .ToLookup(x => x.t, x => x.a);

答案 1 :(得分:0)

使用GroupBy的另一种方法。虽然有点复杂。

articles.SelectMany(article => article.Tags)
        .Distinct()
        .GroupBy(tag => tag, tag => articles.Where(a => a.Tags.Contains(tag)))
        .ToDictionary(group => group.Key, 
                      group => group.ToList().Aggregate((x, y) => x.Concat(y).Distinct()));