在列表中创建一个带有分组的字典

119

我有一个对象在一个列表中:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}
现在,我想从中创建以下字典:
Dictionary<int, List<DemoClass>>

我想按照属性GroupKeyList<DemoClass>进行分组,但我不知道如何实现,需要一些帮助。

经过一番思考,我通过以下方式实现了所需的行为:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

但是,有没有一种方法可以将这个操作合成为一个语句?

4个回答

221

为了让mquander的建议更加具体:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
你当然可以使用更短的变量名称来缩短它:)
不过,我能否建议您使用Lookup? Lookup基本上是从键到IEnumerable<T>的字典——除非您真的需要将值作为列表,否则通过ToLookup调用可以使代码更短(而且更高效)。
var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

1
我认为在长期环境中,与构建字典相比,查找执行效果不佳,因为它需要为每个请求重新生成结果...如果我错了,请纠正我! - user57508
不,它创建整个查找。通常,ToXXX 不使用延迟执行。 - Jon Skeet
1
(您可能正在考虑分组,这确实是延迟的。) - Jon Skeet
1
如果我不那么心胸狭窄,我会给你点赞的。最初是因为Linq而来,但留下了一个我从未听说过的数据结构! - Chris McCall
2
@sasikt:这个模型是你可以查找任何东西,如果键不存在,你只会得到一个空集合。在我看来,这通常比TryGetValue方法更有用。 - Jon Skeet
显示剩余3条评论

92
var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

这个会起作用!!!


7

你已经将它变成了一行代码。只需在第一行末尾加上 ToDictionary 即可。如果您想让它更短,请使用函数组合语法,而不是查询语法。


4

我稍微偏离话题了,但我来到这个帖子是因为我在寻找一种在Linq中创建字典的方法,而这里的对话引导我找到了答案...

您可以使用Linq创建多级字典,这对于您想要按多个键或维度进行搜索的场景非常有用。诀窍是创建一个分组,然后将其转换为字典,如下所示:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

生成的查询可以按以下方式使用:
 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

希望这对需要此类查询的其他人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接