【问题标题】:Merging IDictionary - is there a more efficient method than this?合并 IDictionary - 还有比这更有效的方法吗?
【发布时间】:2012-05-01 13:58:11
【问题描述】:

我有一个助手,它通过连接TValueToString() 方法将两个或多个IDictionary<TKey, TValue> 对象合并为一个IDictionary<TKey, string>,如下所示:

public class DictionaryHelper<TKey, TValue>
{
    public static IDictionary<TKey, string> MergeDictionaries<TKey, TValue>(params IDictionary<TKey, TValue>[] dictionaries) where TValue : class
    {
        var returnValue = new Dictionary<TKey, string>();
        foreach (var dictionary in dictionaries)
        {
            foreach (var kvp in dictionary)
            {
                if (returnValue.ContainsKey(kvp.Key))
                {
                    returnValue[kvp.Key] += kvp.Value.ToString();
                }
                else
                {
                    returnValue[kvp.Key] = kvp.Value.ToString();
                }
            }
        }
        return returnValue;
    }

}

虽然这很简单,也很容易阅读,但似乎应该有一种更有效的方法来做到这一点。有吗?

【问题讨论】:

  • 记住kvp.Value can be null. 高效的速度还是高效的代码行数?
  • 嗯...好吧,我的预期用途不允许这样做,但我同意我需要处理它。感谢您指出了这一点。高效的性能...我不介意在前面多花点力气。
  • 这可能会有所帮助:stackoverflow.com/questions/712927/…

标签: c# performance


【解决方案1】:

我不知道这是否更有效,但至少它更短:

var result = dictionaries.SelectMany(d => d)
                         .ToLookup(kvp => kvp.Key, kvp => kvp.Value)
                         .ToDictionary(g => g.Key, g => string.Concat(g));

【讨论】:

  • @JeremyHolovacs:如果我们用你的作为基线,他们都是平等的。 (此评论的先前版本包括延迟创建字典的时间
  • 有趣。所以编译器或多或少地对待它们是一样的。然后一切都与可读性有关。
  • @Jeremy:这意味着更慢,但我错误地将延迟对象创建包含在计时中。随着您增加字典的大小和匹配的数量,dtb 比您的代码具有轻微优势(1.05 加速)。
【解决方案2】:

您可以使用SelectMany 删除可见 foreach

foreach (var kvp in dictionaries.SelectMany(dd => dd))
{
    if (returnValue.ContainsKey(kvp.Key))
    {
        returnValue[kvp.Key] += kvp.Value.ToString();
    }
    else
    {
        returnValue[kvp.Key] = kvp.Value.ToString();
    }
}

你可以进一步扩展它,although dtb's is more elegant and efficient:

var merged = dictionaries.SelectMany(dd => dd)
                         .GroupBy(kvp => kvp.Key, kvp => kvp.Value)
                         .ToDictionary(
                             gg => gg.Key,
                             gg => String.Concat(gg));

但是,这可能不会比您当前的方法更有效或更易读。

【讨论】:

  • 您可以将.GroupBy(kvp =&gt; kvp.Key).ToDictionary(..) 替换为.GroupBy(kvp =&gt; kvp.Key, kvp =&gt; kvp.Value).ToDictionary(g =&gt; g.Key, g =&gt; string.Concat(g))。因此,除了 GroupBy 而不是 ToLookup 之外,它与我的答案完全相同。我想知道哪个更有效...
  • 谢谢,我的直觉说 L2O 不会有任何区别,ILSpy 显示在 L2O 中使用 GroupBy 只是推迟了对 Lookup&lt;TKey, TElement&gt;.Create&lt;TSource&gt;() 的调用,ToLookup 立即使用。不确定有什么不同,除了我正在制作一个Lookup 而你的已经有了它。
【解决方案3】:

您可以使用TryGetValue 来合并源值的位置和检索。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-16
    • 2014-07-10
    • 2020-11-29
    • 2011-07-03
    • 2020-03-13
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    相关资源
    最近更新 更多