[英]LINQ: group by a field that is a list
我有一个 Publication 对象列表:
public class Publication
{
public List<string> Authors { get; set; }
}
我想使用 LINQ 按作者对我的发布对象进行分组。 我的解决方案使用字典,如下所示:
var dict = new Dictionary<string, List<Publication>>();
foreach (var publication in list)
{
foreach(var author in publication.Authors)
{
if (dict.ContainsKey(author))
{
dict[author].Add(publication);
}
else
{
dict.Add(author, new List<Publication> { publication });
}
}
}
然而,这对我来说似乎很丑陋。 这个问题一定有一个简单而优雅的单线,但我无法直截了当。 我还尝试在 Authors 属性上使用 selectmany 将列表展平,然后将它们分组,但它只去除了作者字符串,并且发布对象消失了。
使用 LINQ,您可以这样做:
var groupedByAuthor = list
.SelectMany(publication =>
publication.Authors.Select(author => new { author, publication }))
.GroupBy(arg => arg.author, keyValue => keyValue.publication)
.ToArray();
但这会慢一点。
您可以使用 Linq 和一些匿名类:
public class Publication
{
public List<string> Authors { get; set; }
public string Title { get; set; }
}
class Program
{
static void Main()
{
IEnumerable<Publication> publications; // YOUR DATA HERE!
var groupsByAuthor = publications.SelectMany(publication => publication.Authors.Select(author => new { Publication = publication, Author = author })).GroupBy(x => x.Author);
foreach (var gba in groupsByAuthor)
{
Console.WriteLine(gba.Key);
foreach (var pub in gba)
{
Console.WriteLine(pub.Publication.Title);
}
}
Console.ReadLine();
}
}
如果您更关心干净和富有表现力的代码,您可能想尝试创建一个扩展方法,而不是强制执行丑陋的 linq 查询。 代码应如下所示。
class Program
{
static void Main(string[] args)
{
List<Publication> test = new List<Publication>();
Dictionary<string, List<Publication>> publicationsByAuther = test.GroupByAuthor();
}
}
public static class Extensions
{
public static Dictionary<string, List<Publication>> GroupByAuther(this List<Publication> publications)
{
Dictionary<string, List<Publication>> dict = new Dictionary<string, List<Publication>>();
foreach (var publication in publications)
{
foreach (var author in publication.Authors)
{
if (dict.ContainsKey(author))
{
dict[author].Add(publication);
}
else
{
dict.Add(author, new List<Publication>
{
publication
});
}
}
}
return dict;
}
}
您可能会考虑将添加新作者与添加出版物的情况分开。 把代码变成这样:
var dict = new Dictionary<string, List<Publication>>();
foreach (var publication in list)
{
foreach (var author in publication.Authors)
{
if (!dict.ContainsKey(author))
dict.Add(author, new List<Publication>());
dict[author].Add(publication);
}
}
它不是 LINQ 也不是一个新的解决方案,但也许它有助于优雅
你也可以这样做:
var dict = pubs.SelectMany(p => p.Authors)
.ToDictionary(
a => a,
a => pubs.Where(p => p.Contains(a)).ToList())
);
没有经过测试,但你明白了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.