What is the best way to iterate over a dictionary?

前端 未结 30 1673
我寻月下人不归
我寻月下人不归 2020-11-22 05:18

I\'ve seen a few different ways to iterate over a dictionary in C#. Is there a standard way?

30条回答
  •  有刺的猬
    2020-11-22 05:43

    I appreciate this question has already had a lot of responses but I wanted to throw in a little research.

    Iterating over a dictionary can be rather slow when compared with iterating over something like an array. In my tests an iteration over an array took 0.015003 seconds whereas an iteration over a dictionary (with the same number of elements) took 0.0365073 seconds that's 2.4 times as long! Although I have seen much bigger differences. For comparison a List was somewhere in between at 0.00215043 seconds.

    However, that is like comparing apples and oranges. My point is that iterating over dictionaries is slow.

    Dictionaries are optimised for lookups, so with that in mind I've created two methods. One simply does a foreach, the other iterates the keys then looks up.

    public static string Normal(Dictionary dictionary)
    {
        string value;
        int count = 0;
        foreach (var kvp in dictionary)
        {
            value = kvp.Value;
            count++;
        }
    
        return "Normal";
    }
    

    This one loads the keys and iterates over them instead (I did also try pulling the keys into a string[] but the difference was negligible.

    public static string Keys(Dictionary dictionary)
    {
        string value;
        int count = 0;
        foreach (var key in dictionary.Keys)
        {
            value = dictionary[key];
            count++;
        }
    
        return "Keys";
    }
    

    With this example the normal foreach test took 0.0310062 and the keys version took 0.2205441. Loading all the keys and iterating over all the lookups is clearly a LOT slower!

    For a final test I've performed my iteration ten times to see if there are any benefits to using the keys here (by this point I was just curious):

    Here's the RunTest method if that helps you visualise what's going on.

    private static string RunTest(T dictionary, Func function)
    {            
        DateTime start = DateTime.Now;
        string name = null;
        for (int i = 0; i < 10; i++)
        {
            name = function(dictionary);
        }
        DateTime end = DateTime.Now;
        var duration = end.Subtract(start);
        return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
    }
    

    Here the normal foreach run took 0.2820564 seconds (around ten times longer than a single iteration took - as you'd expect). The iteration over the keys took 2.2249449 seconds.

    Edited To Add: Reading some of the other answers made me question what would happen if I used Dictionary instead of Dictionary. In this example the array took 0.0120024 seconds, the list 0.0185037 seconds and the dictionary 0.0465093 seconds. It's reasonable to expect that the data type makes a difference on how much slower the dictionary is.

    What are my Conclusions?

    • Avoid iterating over a dictionary if you can, they are substantially slower than iterating over an array with the same data in it.
    • If you do choose to iterate over a dictionary don't try to be too clever, although slower you could do a lot worse than using the standard foreach method.

提交回复
热议问题