Development Tip

사전을 반복하고 값을 변경하는 방법은 무엇입니까?

yourdevel 2020. 11. 10. 22:21
반응형

사전을 반복하고 값을 변경하는 방법은 무엇입니까?


Dictionary<string,double> myDict = new Dictionary();
//...
foreach (KeyValuePair<string,double> kvp in myDict)
 {
     kvp.Value = Math.Round(kvp.Value, 3);
}

"속성 또는 인덱서 'System.Collections.Generic.KeyValuePair.Value'를 할당 할 수 없습니다. 읽기 전용입니다."라는 오류가 발생합니다. 값을
반복 myDict하고 변경하려면 어떻게해야합니까?


MSDN 에 따르면 :

foreach 문은 열거자를 둘러싼 래퍼로, 컬렉션에 쓰기가 아닌 읽기만 허용합니다.

이것을 사용하십시오 :

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);
}

게으른 프로그래머의 경우 :

Dictionary<string, double> dictionary = new Dictionary<string, double>();
foreach (var key in dictionary.Keys.ToList())
{
   dictionary[key] = Math.Round(dictionary[key], 3);
}

반복하는 동안 사전을 변경해서는 안됩니다. 그렇지 않으면 예외가 발생합니다.

따라서 먼저 키-값 쌍을 임시 목록에 복사 한 다음이 임시 목록을 반복 한 다음 사전을 변경합니다.

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();

출력 (내 컴퓨터에서) :

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.


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

yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))

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


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);
}

While iterating over the dictionary directly is not possible because you get an exception (like Ron already said), you don't need to use a temp list to solve the problem.

Instead use not the foreach, but a for loop to iterate through the dictionary and change the values with indexed access:

Dictionary<string, double> myDict = new Dictionary<string,double>();
//...    
for(int i = 0; i < myDict.Count; i++) {
    myDict[myDict.ElementAt(i).Key] = Math.Round(myDict.ElementAt(i).Value, 3);
}

Loop through the keys in the dictionary, not the KeyValuePairs.

Dictionary<string, double> myDict = new Dictionary<string, double>();
//...
foreach (string key in myDict.Keys)
{
    myDict[key] = Math.Round(myDict[key], 3);
}

참고URL : https://stackoverflow.com/questions/2260446/how-to-iterate-through-dictionary-and-change-values

반응형