我真的很想理解聚合是如何工作的,我有一个解决方案将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;
}
});
据我所知,Aggregate
没有查询语法(有关更多信息,请参阅documentation)。文档还应该能够解释函数的工作原理。
您正在使用的重载是获取聚合的初始值(第一个参数),并将累加函数(第二个参数)应用于每个元素,返回中间聚合值。因此,您的示例从输入数据生成3个字符串,基本上返回每个键的最后一个字符串值(或者当输入数据不包含该键的任何项时default(string)
)。
如果这是您的要求,您不需要(也不应该)使用聚合函数,因为您没有聚合。您可以使用以下示例获得相同的结果(假设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();