使用LINQ构建字典
c#
假设我们有一个变量“数据”,它是 Id 和 Child Id 的列表:
var data = new List<Data>
{
new()
{
Id = 1,
ChildIds = new List<int> {123, 234, 345}
},
new()
{
Id = 1,
ChildIds = new List<int> {123, 234, 345}
},
new()
{
Id = 2,
ChildIds = new List<int> {678, 789}
},
};
我想要一本包含 ChildId 和相关 Id 的字典。如果 ChildId 已经在字典中,它应该用新的 Id 覆盖。
目前我有这个代码:
var dict = new Dictionary<int, int>();
foreach (var dataItem in data)
{
foreach (var child in dataItem.ChildIds)
{
dict[child] = dataItem.Id;
}
}
这工作正常,但我不喜欢我使用两个循环的事实。我更喜欢使用 Linq ToDictionary 以函数式方式构建字典。使用 Linq 构建字典的最佳方法是什么?
为什么?我更喜欢函数式代码而不是改变状态。除此之外,我只是好奇如何使用 Linq 来构建字典;-)
回答
在这种情况下,您的 foreach 方法既可读又高效。因此,即使我是 LINQ 的粉丝,我也会使用它。循环的好处是您可以轻松调试它或在必要时添加日志记录(例如无效的 ID)。
但是,如果您想使用 LINQ,我可能会使用SelectMany和ToLookup。前者用于像这样展平子集合ChildIds,后者用于创建一个与您的字典非常相似的集合。但一个区别是它允许重复键,在这种情况下你会得到多个值:
ILookup<int, int> idLookup = data
.SelectMany(d => d.ChildIds.Select(c => (Id:d.Id, ChildId:c)))
.ToLookup(x => x.ChildId, x => x.Id);
现在您已经拥有所需的一切,因为它可以像字典一样使用,具有相同的查找性能。如果您无论如何都想创建该字典,您可以使用:
Dictionary<int, int> dict = idLookup.ToDictionary(x => x.Key, x => x.First());
如果你想用新的 Id 覆盖重复项,如上所述,只需使用Last().
.NET-小提琴:https : //dotnetfiddle.net/mUBZPi
- This should be marked as correct answer. All of the other answers are either "wrong" or not as good.