我真的很想了解聚合的工作原理,并且有一个解决方案可以将IEnumerable映射到较新的C#7元组。
我想,如果将其编写为Linq Sql语法,我可以理解得更多。
有人愿意刺它吗?
IEnumerable<(string Key, string Value)> many = DataToPivot();
(string XXXX, string YYYY, string ZZZZ) agg =
many.Aggregate((XXXX: default(string),
YYYY: default(string),
ZZZZ: default(string)),
(a, i) =>
{
switch (i.Key)
{
case "xxxx":
return (i.Value, a.YYYY, a.ZZZZ);
case "yyyy":
return (a.XXXX, i.Value, a.ZZZZ);
case "zzzz":
return (a.XXXX, a.YYYY, i.Value);
default:
return a;
}
});
答案 0 :(得分:2)
据我所知Aggregate
没有查询语法(有关更多信息,请参见documentation)。该文档还应该能够解释该功能的工作原理。
您正在使用的重载获取聚合的初始值(第一个参数),并将累加函数(第二个参数)应用于每个元素,并返回中间的聚合值。因此,您的示例从输入数据中生成了3个字符串,基本上返回了每个键的最后一个字符串值(如果输入数据不包含该键的任何项目,则返回default(string)
。
如果这是您的要求,则您(也不应该)不需要使用Aggregate函数,因为您没有进行聚合。您可以通过以下示例获得相同的结果(假设所有键都出现在many
输入中):
IEnumerable<(string Key, string Value)> many = DataToPivot();
var d = many.GroupBy(i => i.Key)
.ToDictionary(g => g.Key, g => g.Last().Value);
(string XXXX, string YYYY, string ZZZZ) agg = (d["xxxx"], d["yyyy"], d["zzzz"]);
如果不需要元组,下面的方法也可以处理数据集中根本不存在键的情况(如果键不存在,则返回默认值):
d.TryGetValue("xxxx", out string x);
d.TryGetValue("yyyy", out string y);
d.TryGetValue("zzzz", out string z);
Aggregate
例如进行字符串连接-但您可以改用String.Join()
:
many.GroupBy(i => i.Key)
.ToDictionary(g => g.Key, g => string.Join(",", g));
如果您仍然想使用Aggrergate
,可以这样重写它:
many.GroupBy(i => i.Key)
.ToDictionary(g => g.Key, g => g.Aggregate((a, i) => i));
这基本上是Last()
使用Aggregate()
实现的;并使用TryGetValue
可以满足您的需求。
更一般的一点:使用这种方法,您可以容纳多个键值,而无需专门对其进行编码。在这种情况下,您甚至可能不需要ToDictionary
调用,例如像这样:
many.GroupBy(i => i.Key)
.Select(g => new { g.Key, Result = g.Aggregate((a, i) => i) })
.ToList();