LINQ 分组为字典对象

Posted

技术标签:

【中文标题】LINQ 分组为字典对象【英文标题】:LINQ Group By into a Dictionary Object 【发布时间】:2011-06-15 17:39:17 【问题描述】:

我正在尝试使用 LINQ 从 List<CustomObject> 创建一个 Dictionary<string, List<CustomObject>>。我可以使用“var”让它工作,但我不想使用匿名类型。这是我所拥有的

var x = (from CustomObject o in ListOfCustomObjects
      group o by o.PropertyName into t
      select t.ToList());

一旦我拥有x,我也尝试使用来自 LINQ 库的Cast<>(),但是我遇到了编译问题,因为它是无效的演员表。

【问题讨论】:

如果你尝试 var x = (from CustomObject o in ListOfCustomObjects group o by o.PropertyName into t select t).ToList(); 有什么理由需要这样做而不是使用为此而设计的 ToLookup? 乔恩,您能否发布一个示例,说明 ToLookup 在这种情况下如何工作?我不熟悉那种 LINQ 方法。 @JonSkeet 你太棒了! (我的意思是,每个人都已经知道了,但仍然。)我不打算使用 ToLookup 的原因是因为我直到现在才听说过它。现在我知道了! 为了完整起见,使用var 不是使用“匿名”类型,而是使用“隐式”类型。匿名类型是编译器创建的用于处理new thing = "stuff" ; 构造的新类。隐式类型是现有的类,var 只是在立即分配变量时引用它们的便捷方式,可以从分配给它的对象的类型推断变量类型。您甚至可以隐式键入引用匿名类型的变量,即:var a = new thing = "stuff" ; 【参考方案1】:
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToDictionary(g => g.Key, g => g.ToList());

【讨论】:

除非您需要来自 'CustomObject' 的属性作为列表值(此答案中未显示),否则值得检查他的代码性 Jon Skeet 对建议 ToLookup() 的问题的评论。 如果需要非不变的结果,这是这样做的方法。 ToLookup 是不可变的。 我的 2 美分(只是因为它让我挣扎了一个小时 :)):按属性分组时,请确保该属性具有价值!否则,Todict 方法无法生成密钥(至少对于字符串属性...):) .GroupBy(o =&gt; o.PropertyName).ToDictionary(g =&gt; g.Key, g =&gt; g.ToList()) 这可能是扩展 Linq 库的一部分。所以我们只需要.ToDictionary(o=&gt;o.PropertyName) @Jaider,已经有了这样的功能:只需将ToDictionary替换为ToLookup即可。【参考方案2】:

我无法对@Michael Blackburn 发表评论,但我猜你投了反对票,因为在这种情况下不需要 GroupBy。

像这样使用它:

var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]

此外,我发现这比使用 GroupBy().ToDictionary() 时执行得更好。

【讨论】:

我在进行音译,没有以最佳方式回答问题。【参考方案3】:

对于@atari2600,这就是在 lambda 语法中使用 ToLookup 的答案:

var x = listOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToLookup(customObject => customObject);

基本上,它采用 IGrouping 并将其具体化为列表字典,其中 PropertyName 的值作为键。

【讨论】:

为什么要投反对票?这不准确/回答问题吗? 如果你错过了,@RuudvK 在his answer 中提到他怀疑否决票是因为 GroupBy 是不必要的。 ToLookup 有一个可以完成工作的重载。 我确实错过了那个回复,感谢您标记我。有道理,分组在语法上是不必要的,我只是把它留在里面以使从查询语法到方法语法的转换更清晰。 GroupBy(只有一个参数的重载)返回一个 IEnumerable> 随后的 ToLookup 然后将其变成一个非常复杂的类型,甚至与 IDictionary> 只是 ToLookup 返回正确的类型。【参考方案4】:

如果您要计算字数,这可能会对您有所帮助。如果您想要一个键和一个项目列表,只需修改代码以使 valuegroup.ToList()

    var s1 = "the best italian resturant enjoy the best pasta";    
    var D1Count = s1.ToLower().Split(' ').GroupBy(e => e).Select(group => new  key = group.Key, value = group.Count() ).ToDictionary(e => e.key, z => z.value);


//show the results
                    Console.WriteLine(D1Count["the"]);
                    foreach (var item in D1Count)
                    
                        Console.WriteLine(item.Key +" "+ item.Value);
                    

【讨论】:

答案有点断章取义,因为它与this question 有关。但是,如果您修改代码以使用 group.ToList() 而不是计数,这将是与接受的答案相同的解决方案:GroupBy,然后是 ToDictionary,而不创建匿名对象。【参考方案5】:

以下内容对我有用。

var temp = ctx.Set<DbTable>()
  .GroupBy(g => new  g.id )
  .ToDictionary(d => d.Key.id);

【讨论】:

以上是关于LINQ 分组为字典对象的主要内容,如果未能解决你的问题,请参考以下文章

linq.js 按javascript中的对象数组分组

使用 linq 将列表转换为字典,而不用担心重复

Linq 选择新对象

LINQ-to-Objects - 不能按对象分组

如何对C#类对象值进行分组。 LINQ可以吗?

如何将字典结果绑定到类对象c#linq