如何将两个字典合并?

3

我有两个字典。如果dict2中的值相同,则需要将dict1中匹配键的值相加,并在结果字典中生成结果,如下所示。

**dict1**                           **dict2**
Id         value                       Id          value
24379      348                         24379       270451
24368      348                         24368       270451
24377       90                         24377       270450
24366       90                         24366       270450
24369       10                         24369       270450   
24300       25

Result:
24379      696
24368      696
24377      190
24366      190
24369      190

我有以下逻辑,希望优化此解决方案:
Dictionary<int, int> result = new Dictionary<int, int>();

foreach (int itemKey in dict1.keys)
{
    result.add (itemKey, dict1.Where(a => dict2.ContainsKey(a.key) 
                                       && dict2.ContiansKey(itemKey) 
                                       && dict2[a.key] == dict2[itemKey])
                              .Sum(a => a.value);
}

然后我们需要从dict1中匹配的键添加值。我从您期望的结果中没有理解到这一点。看起来您正在乘以二,而不是将它们加在一起。 - Patrick Hofman
1
@PatrickHofman dict22437924368 的值都是 270451,所以 OP 从 dict1 中加起来的值也都是 348 - Sergey Kalinichenko
1
什么样的设计啊!真是一团糟 @dasblinkenlight - M.kazem Akhgary
@M.kazemAkhgary 这就是 OP 想要的 - 或许他无法控制字典中的内容。 - Sergey Kalinichenko
你所说的并没有太多意义。为什么不举一个例子,至少其中一个键不在dic2中呢? - paparazzo
Dict2 可能有超过 2 个匹配条目,或者可能没有匹配条目。 - Raj
3个回答

3
你可以分两步进行:
  • 准备一个字典,通过 dict2 的值来查找对应的值
  • 遍历 dict1,并从查找字典中插入值
以下是具体操作步骤:
var lookup = dict1
    .Where(p => dict2.ContainsKey(p.Key))
    .GroupBy(p => dict2[p.Key])
    .ToDictionary(g => g.Key, g => g.Sum(p => p.Value));
var res = dict1.Keys
        .Where(k => dict2.ContainsKey(k))
        .ToDictionary(k => k, k => lookup[dict2[k]]);

Demo.


1
public static void DicAddTest()
{
    Dictionary<int, int> dic1 = new Dictionary<int, int>() { {24379,348}, { 24368, 348 }, { 24377, 90 }, { 24366, 90 } };
    Dictionary<int, int> dic2 = new Dictionary<int, int>() { { 24379, 270451 }, { 24368, 270451 }, { 24377, 270450 }, { 24366, 270450 } };
    Dictionary<int, int> dicResult = DicAdd(dic1, dic2);
    foreach (KeyValuePair<int, int> kvp in dicResult)
        Debug.WriteLine("{0} {1}", kvp.Key, kvp.Value);
    Debug.WriteLine("");
}
public static Dictionary<int, int> DicAdd(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
    Dictionary<int, int> dicResult = new Dictionary<int, int>(dic1);
    foreach (int k in dic1.Keys.Where(x => dic2.Keys.Contains(x)))
        dicResult[k] = dicResult[k] + dicResult[k];
    return dicResult;
}

问题不清楚
public static Dictionary<int, int> DicAdd2(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
    Dictionary<int, int> dicResult = new Dictionary<int, int>();
    foreach (KeyValuePair<int, int> kvp in dic1.Where(x => dic2.Keys.Contains(x.Key)))
        dicResult.Add(kvp.Key, 2 * kvp.Value);
    return dicResult;
}

1
两个代码的结果与问题中的代码不同。请使用 dic1 = new Dictionary<int, int>() { {24379,1}, { 24368, 10 }, { 24377, 100 }, { 24366, 1000 } }; 进行检查。问题中的结果是 { {24379,11}, { 24368, 11 }, { 24377, 1100 }, { 24366, 1100 } },而你的结果是 { {24379,2}, { 24368, 20 }, { 24377, 200 }, { 24366, 2000 } } - Sir Rufo
1
我完全不明白为什么 OP 接受了这个答案。虽然问题的英文部分可能不太清楚,但是 C# 部分明确表明了 OP 想要什么。你的代码忽略了 dic2 的值,而是将 dic1 中的值乘以 2。这是错误的,并且在稍微改变数字时会产生与 OP 代码不同的答案(演示)。 - Sergey Kalinichenko
如果问题不清楚,我们可以投票关闭“不清楚你在问什么”或留下评论。接受这个答案让我感觉到,问题对于提问者也不清楚 :o) - Sir Rufo
我正在测试今天给出的解决方案,但对于这种情况它并没有按预期工作。 Dictionary<int, int> dic1 = new Dictionary<int, int>() { { 24379, 348 }, { 24368, 348 }, { 24377, 90 }, { 24366, 90 }, { 24367, 10 } }; Dictionary<int, int> dic2 = new Dictionary<int, int>() { { 24379, 270451 }, { 24368, 270451 }, { 24377, 270450 }, { 24366, 270450 }, { 24367, 270450 } }; 对于24367,我得到的是180而不是190。 - Raj
我完全不明白为什么你会期望190。答案只有在问题清晰的情况下才是好的。 - paparazzo

0
也许这样做会更容易,如果您不确定dict1和dict2将具有相同的键:
var result = new Dictionary<int, int>();

foreach(var kvp in dict1)
{
    int value;

    if(dict2.TryGetValue(kvp.Key, out value))
    {
        result[kvp.Key] = kvp.Value * 2;
    }
}

这将仅添加在两个字典中均存在的值。如果您的字典非常大,您可以考虑使用Parallel For或考虑使用Hashtable


不能在枚举中修改集合。 - paparazzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接