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 => o.PropertyName).ToDictionary(g => g.Key, g => g.ToList())
这可能是扩展 Linq 库的一部分。所以我们只需要.ToDictionary(o=>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如果您要计算字数,这可能会对您有所帮助。如果您想要一个键和一个项目列表,只需修改代码以使 value 为 group.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 分组为字典对象的主要内容,如果未能解决你的问题,请参考以下文章