【问题标题】:Merge multiple dictionaries and aggregate values where required在需要时合并多个字典和聚合值
【发布时间】:2018-04-25 14:57:01
【问题描述】:

我通过在 LINQ 中的 GroupBy 投影上调用 ToDictionary 创建了三个字典。

var dictionaryOne = _repositoryOne.GetData()
.GroupBy(d => new { d.Property1, d.Property2, d.LocalCcyId})
.ToDictionary(d =>
    new
    {
        d.Key.Property1,
        d.Key.Property2,
        d.Key.LocalCcyId
    },
    v => v.Sum(l => ConvertToUsd(effectiveDate, l.LocalCcyId, l.Amount))); 

var dictionaryTwo = _repositoryTwo.GetData()
.GroupBy(d => new { d.Property1, d.Property2, d.LocalCcyId})
.ToDictionary(d =>
    new
    {
        d.Key.Property1,
        d.Key.Property2,
        d.Key.LocalCcyId
    },
    v => v.Sum(l => ConvertToUsd(effectiveDate, l.LocalCcyId, l.Balance))); 

var dictionaryThree = _repositoryThree.GetData()
.GroupBy(d => new { d.Property1, d.Property2, d.LocalCcyId})
.ToDictionary(d =>
    new
    {
        d.Key.Property1,
        d.Key.Property2,
        d.Key.LocalCcyId
    },
    v => v.Sum(l => ConvertToUsd(effectiveDate, l.LocalCcyId, l.Total))); 

我想将这些合并到字典中,然后 i) 总结以美元为单位的值 & ii) 从 Key 中删除按 LocalCcyId 列分组

三个字典中的每一个中都会出现相同键的实例,我需要汇总所有此类情况的总和。如何在 LINQ 中实现这一点?

【问题讨论】:

  • 在调用ToDictionary 之前,为什么不直接Concat 数据源?
  • 我可以试试。每个来源的数据结构都非常不同,我必须对每个来源进行额外的 Select 以使它们与 Concat 一起使用。
  • @nvoigt - 我试过但无法让它工作。如果我在 GroupBy 之后执行 Select,那么我无法调用 ToDictionary

标签: c# linq


【解决方案1】:

在我看来,这就是你所需要的:

var finalDictionary =
    dictionaryOne
        .Concat(dictionaryTwo)
        .Concat(dictionaryThree)
        .GroupBy(x => new { x.Key.Property1, x.Key.Property2 }, x => x.Value)
        .ToDictionary(x => new { x.Key.Property1, x.Key.Property2 }, x => x.Sum());

或者,使用 LINQ 语法(尽可能):

var finalDictionary =
(
    from x in dictionaryOne.Concat(dictionaryTwo).Concat(dictionaryThree)
    group x.Value by new { x.Key.Property1, x.Key.Property2 }
)
    .ToDictionary(x => new { x.Key.Property1, x.Key.Property2 }, x => x.Sum());

【讨论】:

  • 谢谢,唯一的问题是每个字典中都有“重复”键。对于这些情况,我需要聚合键(Sum)的值。
  • @RahulMisra - 不,这应该不是问题。 group by 消除了重复项。
  • 确实如此。可以肯定的是,我查看了 Concat 实现,它只返回给它的每个集合中的所有元素,然后 GroupBy 完成聚合它的工作。我将结果与另一个三个 foreach 循环块进行了比较,该循环遍历每个字典并在遇到之前看到的键时聚合值。两种情况下的数字完全匹配。我现在更好地理解了这一点。非常感谢!
【解决方案2】:

假设您正在查询远程数据源,对数据运行两次查询或两次转换为 USD 似乎并不比使用字典并组合它们更有效,所以我就是这样做的。

首先,您需要将每个 Dictionary 转换为具有所需数据的新匿名对象,然后按属性对值求和:

var allDictionary = dictionaryOne.Select(kv => new { kv.Key.Property1, kv.Key.Property2, kv.Value })
                                 .Concat(dictionaryTwo.Select(kv => new { kv.Key.Property1, kv.Key.Property2, kv.Value }))
                                 .Concat(dictionaryThree.Select(kv => new { kv.Key.Property1, kv.Key.Property2, kv.Value }))
                                 .GroupBy(k2v => new { k2v.Property1, k2v.Property2 })
                                 .ToDictionary(k2vg => new { k2vg.Key.Property1, k2vg.Key.Property2 }, k2vg => k2vg.Sum(k2v => k2v.Value));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2016-11-29
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    相关资源
    最近更新 更多