What's the best way to set all values in a C# Dictionary<string,bool>?

37,095

Solution 1

That is a reasonable approach, although I would prefer:

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

The call to ToList() makes this work, since it's pulling out and (temporarily) saving the list of keys, so the iteration works.

Solution 2

A one-line solution:

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

Solution 3

If you aren't using tri-state bools, then you can use HashSet<string>, and call Clear() to set the values to "false".

Solution 4

I'm not sure if it's the best way but I was looking something on a single line and this worked for me

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

Solution 5

I profiled the difference between Billy's and Reed's solutions. Polaris878, take good note of the results and remember that premature optimization is the root of all evil ;-)

I rewrote the solutions in VB (because I'm currently programming in that language) and used int keys (for simplicity), otherwise it's the exact same code. I ran the code with a dictionary of 10 million entries with a value of "true" for each entry.

Billy Witch Doctor's original solution:

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

Elapsed milliseconds: 415

Reed Copsey's solution:

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

Elapsed milliseconds: 395

So in that case the foreach is actually faster.

Share:
37,095
MsBao
Author by

MsBao

Updated on April 08, 2021

Comments

  • MsBao
    MsBao about 3 years

    What's the best way to set all values in a C# Dictionary?

    Here is what I am doing now, but I'm sure there is a better/cleaner way to do this:

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

    I have tried some other ways with foreach, but I had errors.

  • Polaris878
    Polaris878 almost 15 years
    See above. Sorry for not providing evidence in the original post.
  • Sam Harwell
    Sam Harwell almost 15 years
    Changing the dictionary invalidates the enumerator, and continuing to use it will throw an InvalidOperationException.
  • Sam Harwell
    Sam Harwell almost 15 years
    The foreach method as listed in the first post is slow ... for manipulating the existing internal buckets of the dictionary.
  • Pavel Minaev
    Pavel Minaev almost 15 years
    The links provided only point out that foreach is slower for arrays, not that it is slower for dictionaries (or in general). Furthermore, the first article is simply outdated, and no longer correct even when applied to arrays; and the second article actually measures the performance of Enumerable.Range rather than foreach as such.
  • Jared Updike
    Jared Updike almost 15 years
    +1 for showing evidence but I disagree with this in practice. for loops in my experience cause more bugs and take more lines of whereas foreach is clearer and the performance hit is negligible for real applications. The benchmarks are on toy programs where the assembly gets highly optimized to deal with arrays of unboxed values AND THAT IS ALL THE CODE IS DOING. In real code it is not likely to effect your run times except inside of tight loops, in which case you are using unsafe/pointers anyway, right?
  • Michael Donohue
    Michael Donohue almost 15 years
    This would be called premature optimization. It is doubtful that a reset algorithm is in the critical path of any algorithm
  • Polaris878
    Polaris878 almost 15 years
    Its still going to be slower going over the list using foreach than going over the list with a for loop...
  • tsuo euoy
    tsuo euoy almost 15 years
    Your links are not evidence. The first link is for an array, and does not even profile the difference. The second link is for Enumerable.Range... for dictionaries the result can be very different.
  • Sam Holder
    Sam Holder almost 15 years
    'but you take too much of a performance hit using it.' - you can't really say this without knowing the use case of the code. if it takes 10ms longer and is run once in the whole app run then the performance hit might not make any difference. if the loop is run 100 million times then maybe you have an argument. -1 for premature optimisation.
  • Polaris878
    Polaris878 almost 15 years
    You don't need an article that pertains directly with Dictionary, since the underlying data structure uses IEnumerable... the findings are true for anything using IEnumerable. @bebop... yes this may not be run 100 million times, but in the managed code world I'm going to take whatever speed I can get.
  • Polaris878
    Polaris878 almost 15 years
    And Reed's answer is converting the dictionary to a list anyways... which, lo and behold, uses an array behind the scenes. So if anything, these articles are perfectly relevant.
  • Summer Sun
    Summer Sun almost 15 years
    @Polaris - I just ran a test iterating through 1 million Dictionary<string, bool> records and changed all their values from true to false. The performance is nearly identical between for and foreach on my machine. Surprisingly, the foreach loop occasionally completed more quickly than the for loop. If however, I do not set any values inside the loop, the for loop will complete twice as quickly. This is meaningless though because the loop isn't actually doing anything.
  • tsuo euoy
    tsuo euoy almost 15 years
    Polaris, check out my answer.
  • MsBao
    MsBao almost 15 years
    I am not using tri-state bools, but I don't understand how to implement what you are talking about. It looks cool, though!
  • MsBao
    MsBao almost 15 years
    Looking at my original code, I don't know why I didn't try this.
  • Sam Harwell
    Sam Harwell almost 15 years
    @Billy: If the string is in the HashSet, then it's true. If it's not in the HashSet, it's false. Use Add/Remove instead of setting true/false. This will be very fast, but there's no way to represent a third "missing" state.
  • Polaris878
    Polaris878 almost 15 years
    Thanks John and Meta, but please note that Reed's and other answers are actually going over a list. But I probably stand corrected on the case when a Dict. is used.
  • Polaris878
    Polaris878 almost 15 years
    Okay nevermind after reading Meta's answer. Sorry for sucking.
  • obenda
    obenda over 8 years
    dict.Keys.ForEach(k =>dict[k] = false);
  • Alex Zhukovskiy
    Alex Zhukovskiy over 7 years
  • Gerardo Marset
    Gerardo Marset over 4 years
    Alternative form: dict = dict.Keys.ToDictionary(x => x, _ => false);
  • Stefan Steiger
    Stefan Steiger over 4 years
    Instead of ToList, use new List(dict.Keys)
  • tymtam
    tymtam about 3 years
    From .NET5 ToList() is not needed. Please see my answer for a github link to the change.
  • MsBao
    MsBao about 3 years
    Good to know that feature has been added