【问题标题】:What's the best way to set all values in a C# Dictionary<string,bool>?在 C# Dictionary<string,bool> 中设置所有值的最佳方法是什么?
【发布时间】:2010-11-13 02:47:50
【问题描述】:

在 C# 字典中设置所有值的最佳方法是什么?

这是我现在正在做的事情,但我确信有更好/更清洁的方法来做到这一点:

Dictionary<string,bool> dict = GetDictionary();
var keys = dict.Keys.ToList();
for (int i = 0; i < keys.Count; i++)
{
    dict[keys[i]] = false;
}

我已经尝试了一些其他的 foreach 方法,但我遇到了错误。

【问题讨论】:

    标签: c# .net generics dictionary


    【解决方案1】:

    这是一个合理的方法,虽然我更喜欢:

    foreach (var key in dict.Keys.ToList())
    {
        dict[key] = false;
    }
    

    ToList() 的调用可以完成这项工作,因为它会拉出并(临时)保存键列表,因此迭代可以进行。

    【讨论】:

    • 看我原来的代码,不知道为什么不试试这个。
    • dict.Keys.ForEach(k =>dict[k] = false);
    • 使用 new List(dict.Keys) 代替 ToList
    • 不需要来自 .NET5 ToList()。请参阅我的答案以获取更改的 github 链接。
    【解决方案2】:

    单线解决方案:

    dict = dict.ToDictionary(p => p.Key, p => false);
    

    【讨论】:

    • 替代形式:dict = dict.Keys.ToDictionary(x =&gt; x, _ =&gt; false);
    【解决方案3】:

    如果您不使用三态布尔值,则可以使用HashSet&lt;string&gt;,并调用Clear() 将值设置为“false”。

    【讨论】:

    • 我没有使用三态布尔值,但我不明白如何实现你所说的。不过看起来很酷!
    • @Billy:如果字符串在HashSet 中,则为真。如果不在HashSet 中,则为假。使用添加/删除而不是设置真/假。这将非常快,但无法表示第三种“缺失”状态。
    【解决方案4】:

    我不确定这是否是最好的方法,但我在单行上寻找一些东西,这对我有用

    mydict.Keys.ToList().ForEach(k => mydict[k] = false);
    

    【讨论】:

      【解决方案5】:

      我分析了比利和里德解决方案之间的区别。 Polaris878,记下结果,记住过早的优化是万恶之源;-)

      我在 VB 中重写了解决方案(因为我目前正在使用该语言进行编程)并使用 int 键(为简单起见),否则它是完全相同的代码。我使用包含 1000 万个条目的字典运行代码,每个条目的值为“true”。

      比利巫医的原始解决方案:

      Dim keys = dict.Keys.ToList
      For i = 0 To keys.Count - 1
          dict(keys(i)) = False
      Next
      

      经过的毫秒数:415

      Reed Copsey 的解决方案:

      For Each key In dict.Keys.ToList
          dict(key) = False
      Next
      

      经过的毫秒数:395

      所以在这种情况下,foreach 实际上更快

      【讨论】:

        【解决方案6】:

        从 .NET5 开始(参见github):

        foreach (var pair in dict) 
            dict[pair.Key] += 1;
        

        .NET5 之前的:

        foreach (var key in dict.Keys.ToList())
            dict[key] += 1;
        

        【讨论】:

        • 很高兴知道该功能已添加
        【解决方案7】:

        您可以直接取出 ToList() 并直接遍历字典项

        Dictionary<string, bool> dict = GetDictionary();
        foreach (var pair in dict) 
        {
            dict[pair.Key] = false;
        }
        

        【讨论】:

        • 更改字典会使枚举器失效,继续使用会抛出InvalidOperationException
        【解决方案8】:

        按照您现在的方式进行操作... foreach 很慢。 foreach 可能更干净,但使用它会对性能造成太大影响。

        编辑:
        http://www.codeproject.com/KB/cs/foreach.aspx
        http://www.madprops.org/blog/for-vs-foreach-performance/

        【讨论】:

        • 见上文。很抱歉没有在原帖中提供证据。
        • 第一篇文章中列出的foreach 方法慢...用于操作字典的现有内部存储桶。
        • 所提供的链接仅指出 foreach 对数组较慢,而不是对字典(或一般而言)较慢。此外,第一篇文章已经过时了,即使应用于数组也不再正确;而第二篇文章实际上衡量的是Enumerable.Range而不是foreach本身的性能。
        • +1 用于显示证据,但在实践中我不同意这一点。根据我的经验,for 循环会导致更多错误并占用更多行,而 foreach 更清晰,并且对于实际应用程序的性能影响可以忽略不计。基准测试是在玩具程序上进行的,其中程序集得到了高度优化,以处理未装箱值的数组,这就是代码所做的一切。在实际代码中,它不太可能影响您的运行时间,除非在紧密循环内,在这种情况下,无论如何您都在使用不安全/指针,对吧?
        • 这称为过早优化。重置算法是否处于任何算法的关键路径是值得怀疑的
        猜你喜欢
        • 2011-09-03
        • 1970-01-01
        • 2015-11-23
        • 2014-09-05
        • 2010-10-26
        • 2016-07-14
        • 2010-12-16
        • 1970-01-01
        相关资源
        最近更新 更多