嵌套 IEnumerable<IDictionary> 到不同类型的嵌套 IEnumerable<IDictionary> 的映射
Posted
技术标签:
【中文标题】嵌套 IEnumerable<IDictionary> 到不同类型的嵌套 IEnumerable<IDictionary> 的映射【英文标题】:Mapping of nested IEnumerable<IDictionary> to a different type of nested IEnumerable<IDictionary> 【发布时间】:2021-04-25 02:32:04 【问题描述】:我需要做一些“奇怪”的映射,而且我尝试了很多事情都没有接近,所以我不确定这是否可能。
我有这个“rowDefinition”:这就像最终数据应该是什么样子的合同,“1A”和东西是我将从服务中获得的数据的 ID
var rowDefinitions = new Dictionary<string, IEnumerable<IDictionary<string, object>>>
["Managers"] = new List<IDictionary<string, object>>
new Dictionary<string, object>
["MANAGER_NAME"] = "1A",
["WEBSITE"] = "3A",
["NIP"] = "4A",
["AUM"] = "5A"
,
["Funds"] = new List<IDictionary<string, object>>
new Dictionary<string, object>
["FUND_NAME"] = "6A",
["CURRENCY"] = "2A",
;
我有这些数据来自这样的服务,每个字典都代表上述结构的一种行
var dataFromService = new List<IDictionary<string, object>>
new Dictionary<string, object>
["1A"] = "manager name 1",
["3A"] = "website 1",
["4A"] = "ni professionals 1",
["5A"] = "aum 1"
,
new Dictionary<string, object>
["1A"] = "manager name 2",
["3A"] = "website 2",
["4A"] = "other ni professional 2",
["5A"] = "one more aum 2"
,
new Dictionary<string, object>
["6A"] = "fund name 4",
["2A"] = "currecy 4",
,
new Dictionary<string, object>
["6A"] = "fund name 5",
["2A"] = "currecy 5",
,
new Dictionary<string, object>
["6A"] = "fund name 6",
["2A"] = "currecy 6",
,
;
我需要根据“rowDefinition”映射这些数据,得到类似这样的东西
var expectedResult = new Dictionary<string, IEnumerable<IDictionary<string, object>>>
["Managers"] = new List<IDictionary<string, object>>
new Dictionary<string, object>
["MANAGER_NAME"] = "manager name 1",
["WEBSITE"] = "website 1",
["NIP"] = "ni professionals 1",
["AUM"] = "aum 1"
,
new Dictionary<string, object>
["MANAGER_NAME"] = "manager name 2",
["WEBSITE"] = "website 2",
["NIP"] = "other ni professional 2",
["AUM"] = "one more aum 2"
,
["Funds"] = new List<IDictionary<string, object>>
new Dictionary<string, object>
["FUND_NAME"] = "fund name 4",
["CURRENCY"] = "currency 4"
,
new Dictionary<string, object>
["FUND_NAME"] = "fund name 5",
["CURRENCY"] = "currency 5"
,
new Dictionary<string, object>
["FUND_NAME"] = "fund name 6",
["CURRENCY"] = "currency 6"
;
["Managers"] 或 ["Funds"] 中的 RowDefinitions 可以有更多的键值对,并且可以有其他的东西,例如 ["Potato"],简而言之,我应该能够修改 rowDefinitions,当然我回来的日期将包括相应的信息
这种工作,但看起来很丑(而且肯定效率不高),我认为这可以用 LINQ 完成,但不知道如何
private void UglyWay(List<IDictionary<string, object>> dataScopeWithDataPoints, IDictionary<string, IEnumerable<IDictionary<string, object>>> rowDefinitions)
var excelData = new Dictionary<string, List<IDictionary<string, object>>>();
foreach (var dataScope in dataScopeWithDataPoints)
foreach (var excelRowDefinition in rowDefinitions)
var rowDefinition = excelRowDefinition.Value.First();
var row = new Dictionary<string, object>();
var found = false;
foreach (var dataPoint in rowDefinition)
if (dataScope.ContainsKey(dataPoint.Value.ToString()))
row[dataPoint.Key] = dataScope[dataPoint.Value.ToString()];
found = true;
if (found)
if (!excelData.ContainsKey(excelRowDefinition.Key))
excelData[excelRowDefinition.Key] = new List<IDictionary<string, object>>();
excelData[excelRowDefinition.Key].Add(row);
return;
如果您需要任何额外信息,请告诉我。
【问题讨论】:
为什么你的行定义有一个字典列表来定义每个?那里只有一个条目是可能的,对吗?数据就是这样来的吗? 您好,谢谢您的回复...对于rowDefinition,是的,只有一个条目是可能的...。现在对于“expectedResult”(与rowDefinition相同的类型)可以有多个条目...我可以从 rowDefinition 中删除这个字典列表,我不能碰巧的是“dataFromService”和“expectedResult” 我能问你点别的吗?如果在 "rowDefinitions" 中,["Manager"] 键还包含 ["Funds"] 的一个字段,如下所示:["Managers"] = new List使用行定义,放入更实用的格式,可以提取每个匹配的数据字典并重新映射:
var ans = rowDefinitions.Select(rd => new rd.Key, Definition = rd.Value.First().Select(kv => new kv.Key, Value = kv.Value.ToString() ) )
.ToDictionary(rd => rd.Key,
rd => dataFromService.Where(d => d.ContainsKey(rd.Definition.First().Value))
.Select(d => rd.Definition.ToDictionary(def => def.Key, def => d[def.Value]))
.ToList()
);
注意:这会创建 Dictionary<string, List<Dictionary<string, object>>>
而不是 Dictionary<string, IEnumerable<IDictionary<string, object>>>
。如果您确实需要IDictionary
和IEnumerable
,您可以将dataFromService
创建的值转换为List<>
。
代码如下:
var ans = rowDefinitions.Select(rd => new rd.Key, Definition = rd.Value.First().Select(kv => new kv.Key, Value = kv.Value.ToString() ) )
.ToDictionary(rd => rd.Key,
rd => dataFromService.Where(d => d.ContainsKey(rd.Definition.First().Value))
.Select(d => (IDictionary<string,object>)rd.Definition.ToDictionary(def => def.Key, def => d[def.Value]))
.ToList()
.AsEnumerable()
);
注意:dataFromService
中的缺失值将导致异常。
如果行定义可能重叠,您可以选择具有所有匹配字段名称的行定义,而不是只测试一个:
var ans2 = rowDefinitions.Select(rd => new rd.Key, Definition = rd.Value.First().Select(kv => new kv.Key, Value = kv.Value.ToString() ).ToList() )
.ToDictionary(rd => rd.Key,
rd => dataFromService.Where(d => rd.Definition.Count == d.Keys.Count && rd.Definition.All(dkv => d.ContainsKey(dkv.Value)))
.Select(d => (IDictionary<string,object>)rd.Definition.ToDictionary(def => def.Key, def => d[def.Value]))
.ToList()
.AsEnumerable()
);
【讨论】:
这简直太完美了......我不在乎缺失值,因为它们都会在那里......非常非常感谢!......以上是关于嵌套 IEnumerable<IDictionary> 到不同类型的嵌套 IEnumerable<IDictionary> 的映射的主要内容,如果未能解决你的问题,请参考以下文章
Protobuf-net:嵌套的 IEnumerable 对象
将 IEnumerable<Ienumerable<T>> 转换为 Dictionary<key,IEnumerable<T>>
C# LINQ 优雅地将 IEnumerable<IGrouping> 转换为 IEnumerable<IEnumerable>?