What's the best way to set all values in a C# Dictionary<string,bool>?
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.
MsBao
Updated on April 08, 2021Comments
-
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 almost 15 yearsSee above. Sorry for not providing evidence in the original post.
-
Sam Harwell almost 15 yearsChanging the dictionary invalidates the enumerator, and continuing to use it will throw an
InvalidOperationException
. -
Sam Harwell almost 15 yearsThe
foreach
method as listed in the first post is slow ... for manipulating the existing internal buckets of the dictionary. -
Pavel Minaev almost 15 yearsThe 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 ofEnumerable.Range
rather thanforeach
as such. -
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 almost 15 yearsThis would be called premature optimization. It is doubtful that a reset algorithm is in the critical path of any algorithm
-
Polaris878 almost 15 yearsIts still going to be slower going over the list using foreach than going over the list with a for loop...
-
tsuo euoy almost 15 yearsYour 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 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 almost 15 yearsYou 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 almost 15 yearsAnd 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 almost 15 years@Polaris - I just ran a test iterating through 1 million
Dictionary<string, bool>
records and changed all their values fromtrue
tofalse
. The performance is nearly identical betweenfor
andforeach
on my machine. Surprisingly, theforeach
loop occasionally completed more quickly than thefor
loop. If however, I do not set any values inside the loop, thefor
loop will complete twice as quickly. This is meaningless though because the loop isn't actually doing anything. -
tsuo euoy almost 15 yearsPolaris, check out my answer.
-
MsBao almost 15 yearsI am not using tri-state bools, but I don't understand how to implement what you are talking about. It looks cool, though!
-
MsBao almost 15 yearsLooking at my original code, I don't know why I didn't try this.
-
Sam Harwell almost 15 years@Billy: If the string is in the
HashSet
, then it's true. If it's not in theHashSet
, 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 almost 15 yearsThanks 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 almost 15 yearsOkay nevermind after reading Meta's answer. Sorry for sucking.
-
obenda over 8 yearsdict.Keys.ForEach(k =>dict[k] = false);
-
Alex Zhukovskiy over 7 years@obenda ForEach considered harmfil.
-
Gerardo Marset over 4 yearsAlternative form:
dict = dict.Keys.ToDictionary(x => x, _ => false);
-
Stefan Steiger over 4 yearsInstead of ToList, use new List(dict.Keys)
-
tymtam about 3 yearsFrom .NET5
ToList()
is not needed. Please see my answer for a github link to the change. -
MsBao about 3 yearsGood to know that feature has been added