How to iterate through Dictionary and change values?

后端 未结 8 441
灰色年华
灰色年华 2020-12-02 17:52
Dictionary myDict = new Dictionary();
//...
foreach (KeyValuePair kvp in myDict)
 {
     kvp.Value = Math.Round(kvp.Value,          


        
相关标签:
8条回答
  • 2020-12-02 18:26

    You shouldn't change the dictionary while iterating it, otherwise you get an exception.

    So first copy the key-value pairs to a temp list and then iterate through this temp list and then change your dictionary:

    Dictionary<string, double> myDict = new Dictionary<string, double>();
    
    // a few values to play with
    myDict["a"] = 2.200001;
    myDict["b"] = 77777.3333;
    myDict["c"] = 2.3459999999;
    
    // prepare the temp list
    List<KeyValuePair<string, double>> list = new List<KeyValuePair<string, double>>(myDict);
    
    // iterate through the list and then change the dictionary object
    foreach (KeyValuePair<string, double> kvp in list)
    {
        myDict[kvp.Key] = Math.Round(kvp.Value, 3);
    }
    
    
    // print the output
    foreach (var pair in myDict)
    {
        Console.WriteLine(pair.Key + " = " + pair.Value);
    }
    
    // uncomment if needed
    // Console.ReadLine();
    

    output (on my machine):

    a = 2.2
    b = 77777.333
    c = 2.346

    Note: in terms of performance, this solution is a bit better than currently posted solutions, since the value is already assigned with the key, and there's no need to fetch it again from the dictionary object.

    0 讨论(0)
  • 2020-12-02 18:33

    For the lazy programmers:

    Dictionary<string, double> dictionary = new Dictionary<string, double>();
    foreach (var key in dictionary.Keys.ToList())
    {
       dictionary[key] = Math.Round(dictionary[key], 3);
    }
    
    0 讨论(0)
  • 2020-12-02 18:35

    According to MSDN:

    The foreach statement is a wrapper around the enumerator, which allows only reading from the collection, not writing to it.

    Use this:

    var dictionary = new Dictionary<string, double>();
    // TODO Populate your dictionary here
    var keys = new List<string>(dictionary.Keys);
    foreach (string key in keys)
    {
       dictionary[key] = Math.Round(dictionary[key], 3);
    }
    
    0 讨论(0)
  • 2020-12-02 18:37

    I noticed that fastest way (at this moment) iterate over Dictionary with modify is:

    //Just a dumb class
    class Test<T>
    {
        public T value;
    
        public Test() { }
        public Test(T v) { value = v; }
    }
    
    Dictionary<int, Test<object>> dic = new Dictionary<int, Test<object>>();
    //Init dictionary
    foreach (KeyValuePair<int, Test> pair in dic)
    {
        pair.Value.value = TheObject;//Modify
    }
    

    VS

    List<int> keys = new List<int>(dic.Keys); //This is fast operation   
    foreach (int key in keys)
    {
        dic[key] = TheObject;
    }
    

    First one takes about 2.2s and second one 4.5s (tested dictionary size of 1000 and repeated 10k time, changing dictionary size to 10 didn't change the ratios). Also there wasn't a big deal with getting the Key list, dictionary[key] value get is just slow VS built in iteration. Also if you want even more speed use hard coded type to dumb ("Test") class, with that I got it about 1.85s (with hard coded to "object").

    EDIT:

    Anna has posted the same solution before: https://stackoverflow.com/a/6515474/766304

    0 讨论(0)
  • 2020-12-02 18:38

    One solution would be to put the keys in a list (or another collection) beforehand and iterate through them while changing the dictionary:

    Dictionary<string, double> dictionary = new Dictionary<string, double>();
    
    // Populate it
    List<string> keys = new List<string>(dictionary.Keys);
    
    foreach (string key in keys)
    {
       dictionary[key] = Math.Round(dictionary[key], 3);
    }
    
    0 讨论(0)
  • 2020-12-02 18:41

    passed some time, but maybe someone is interested in it:

    yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))
    
    0 讨论(0)
提交回复
热议问题