繁体   English   中英

LinQ C#-根据对象列表中包含的字符串对对象列表进行分组 <string> 属性

[英]LinQ C# - Grouping a list of objects depending on strings contained in their List<string> property

我对字符串列表进行分组有问题。

我的类“ Post”包含一个称为“标签”的List属性:

public class Post
{
    public string Title { get; set; }
    public int Position { get; set; }
    public List<string> Tags { get; set; }
}

我在代码的其他位置将所有帖子收集在一个列表中。 现在,这些帖子中有许多彼此共享标签。 假设:

Post_1.Tags = new List<string>(){"a", "b", "c"};
Post_2.Tags = new List<string>(){"a", "d", "e"};
Post_3.Tags = new List<string>(){"b", "c", "d"};
Post_4.Tags = new List<string>(){"c", "d", "f"};

我试图获得具有这种结构的集合:

Key: a; Values: Post_1, Post_2;
Key: b; Values: Post_1, Post_3;
Key: c; Values: Post_1, Post_3, Post_4;
Key: d; Values: Post_2, Post_3, Post_4;
Key: e; Values: Post_2;
Key: f; Values: Post_4;

我想我需要使用GroupBy(),但是由于语法的限制,

List<Post> Posts = // all my posts
ILookup<string, Post> ByTag = Posts.GroupBy(p => p.Tags) ...

显然是针对标签列表,而不是单个标签。

有什么建议么?

var tags = Posts.SelectMany(p => p.Tags).Distinct();
var groups = from p in Posts
    from t in tags.Where(tag => p.Tags.Contains(tag))
    group p by t
    into gr
    select gr;

说明 SelectMany.Distinct-使IEnumerable,它包含来自所有帖子的所有标签,没有重复。 来自的前2个-加入标签和帖子。 加入条件-帖子中应包含标签。 结果集合将包含所有可能的帖子对及其标签。 分组将以某种方式将这些对分组,即gr的键将是一个标签,gr将是具有该标签的所有帖子的集合。 我习惯了字典并编写了一个代码,以后可以通过调用ToDictionary(g => g.Key, g => g.ToList())将其转换为Dictionary<string, List<Post>> 如果要查找,则不需要组部分:

var tags = Posts.SelectMany(p => p.Tags).Distinct();
var postAndTagPairs = from p in Posts
    from t in tags.Where(tag => p.Tags.Contains(tag))
    select new {t, p};
var lookup = postAndTagPairs.ToLookup(pat => pat.t, pat => pat.p);

您首先需要获得一个独特的标签列表。 假设帖子在这样的列表中:

var posts = new List<Post>
{
    new Post { Tags = new List<string>(){"a", "b", "c"} },
    new Post { Tags = new List<string>(){"a", "d", "e"} },
    new Post { Tags = new List<string>(){"b", "c", "d"} },
    new Post { Tags = new List<string>(){"c", "d", "f"} }
};

您会得到如下标签:

var allTags = posts.SelectMany(p => p.Tags).Distinct();

然后,您可以进行分组:

var result = from p in posts
             from t in allTags.Where(t => p.Tags.Contains(t))
             group p by t into grp
             select grp;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM