LINQ:按列表字段分组

时间:2018-03-21 16:53:47

标签: c# linq

我有一个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来压缩列表,然后将它们分组,但它只删除了作者字符串,并且发布对象消失了。

5 个答案:

答案 0 :(得分:3)

使用LINQ,您可以这样做:

var groupedByAuthor = list
    .SelectMany(publication => 
        publication.Authors.Select(author => new { author, publication }))
    .GroupBy(arg => arg.author, keyValue => keyValue.publication)
    .ToArray();

但这会慢一些。

答案 1 :(得分:0)

您可以使用Linq和一些匿名类:

return getField(thisPath, field.children)

答案 2 :(得分:0)

如果你更关心干净和富有表现力的代码,你可能想尝试创建一个扩展方法而不是强制一个丑陋的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;
    }
}

答案 3 :(得分:0)

您可能会考虑将添加新作者与添加发布的情况分开。将代码转换成类似的东西:

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而不是一个新的解决方案,但也许它可以帮助关于优雅

答案 4 :(得分:-1)

你也可以这样做:

var dict = pubs.SelectMany(p => p.Authors)
               .ToDictionary(
                   a => a, 
                   a => pubs.Where(p => p.Contains(a)).ToList())
               );

未经测试,但您明白了。