【问题标题】:Adding the contents of 2 dictionaries when keys match, merging otherwise当键匹配时添加2个字典的内容,否则合并
【发布时间】:2013-06-11 11:00:59
【问题描述】:

我有一个爬虫,它按目录汇总文件类型。

类似:

Class Directory
    Property Name As String
    Property TypeBreakdown As Dictionary(Of String, Integer)
    Property Directories As ICollection(Of Directory)
End Class

我递归到目录并添加一个Directory 作为适当的。当我展开堆栈时,我想汇总子目录细分。例如。

假设Source 目录有一个.cpp 文件和2 个子目录(SubDir、SubDir2),我想要这样的东西...

{
    "Name": "Source",
    "TypeBreakdown": {".cpp": 1, ".exe": 10, ".c": 110},
    "Directories": [
        {
            "Name": "SubDir",
            "TypeBreakdown": {".exe": 10, ".c": 10},
            "Directories": [],
        },
        {
            "Name": "SubDir2",
            "TypeBreakdown": {".c": 100},
            "Directories": [],
        }
    ]
}

我正在创建各种 TypeBreakdown 字典,但不确定如何组合:

如果一个键存在于其中一个而不是两个中,则包括键和值。如果键在两者中都存在,则包括键并对值求和。

有没有办法做到这一点,而不需要一个非常笨拙的 for 循环来检查每个键?

这需要在没有框架更新的情况下在 Vista 上运行,这意味着我的目标是 3.0,因此无法访问 LINQ

【问题讨论】:

  • @SWeko 感谢您的编辑,但任何 .Net 语言都可以——我只是碰巧在 VB 中给出了示例。

标签: .net dictionary coding-style


【解决方案1】:

您应该能够使用分组。比如:

var combinedTypeBreakDown = 
    firstTypeBreakDown.Concat(secondTypeBreakDown)
       .GroupBy(kvp => kvp.Key, kvp => kvp.Value)
       .ToDictionary(g => g.Key, g => g.Sum());

【讨论】:

  • 抱歉,我应该提到 - 这需要在没有框架更新的情况下在 Vista 上运行,所以我的目标是 3.0 = 无 LINQ
  • 明白了。你知道LinqBridge吗?也可通过NuGet 获得。
  • @SWeko 不在vanilla 3.0 中。它在 3.5 中到达。并感谢 shamp00,我不知道 LinqBridge - 现在阅读,谢谢 :)
【解决方案2】:

没有 Linq:

    public Dictionary<string, int> CombineDictionaries(params Dictionary<string, int>[] dictionariesToCombine)
    {
        Dictionary<string, int> result = new Dictionary<string, int>();
        foreach (Dictionary<string, int> dictionary in dictionariesToCombine)
        {
            foreach (var item in dictionary)
            {
                if (result.ContainsKey(item.Key))
                    result[item.Key] += item.Value;
                else
                    result.Add(item.Key, item.Value);
            }
        }
        return result;
    }

你用它来称呼它

var combinedBreakDown = CombineDictionaries(firstTypeBreakDown, secondTypeBreakDown);

【讨论】:

    【解决方案3】:

    对于您的具体情况,我认为最好将组合细分作为属性添加到 Directory 类,如下所示:

    public Dictionary<string, int> GetFullTypeBreakdown()
    {
      //assumes the client will not write to the result :D
      if ((Directories == null) || (Directories.Count == 0))
        return TypeBreakdown;
    
      var result = TypeBreakdown
        .Concat(Directories.SelectMany(d => d.GetFullTypeBreakdown()))
        .GroupBy(item => item.Key, item => item.Value)
        .ToDictionary(g => g.Key, g=> g.Sum());
      result.Dump();
    
      return result;
    }
    

    这会在树上递归并计算组合细分。但是,这使用了很多LINQ,所以你至少应该使用LinqBridge(我以前用过它,它是一个救命稻草)

    【讨论】:

      猜你喜欢
      • 2021-01-10
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 2015-10-30
      • 2019-01-11
      • 2022-01-26
      • 2013-08-07
      • 1970-01-01
      相关资源
      最近更新 更多