사전에서 숫자 값 증가
아래 코드를 사용하여 사전에 값을 늘리거나 삽입합니다. 증가하는 키가 존재하지 않는 경우 값을 1로 설정하고 싶습니다.
public void IncrementCount(Dictionary<int, int> someDictionary, int id)
{
int currentCount;
if (someDictionary.TryGetValue(id, out currentCount))
{
someDictionary[id] = currentCount + 1;
}
else
{
someDictionary[id] = 1;
}
}
이것이 적절한 방법입니까?
편리한 upsert 메소드 인 AddOrUpdate가있는 ConcurrentDictionary를 사용하는 것이 이치에 맞았습니다.
그래서 방금 사용했습니다.
someDictionary.AddOrUpdate(id, 1, (id, count) => count + 1);
귀하의 코드는 괜찮습니다. 그러나 다음은 코드에서 분기 할 필요가없는 방식으로 단순화하는 방법입니다.
int currentCount;
// currentCount will be zero if the key id doesn't exist..
someDictionary.TryGetValue(id, out currentCount);
someDictionary[id] = currentCount + 1;
이는 키가 존재하지 않는 경우 TryGetValue메서드 value가 해당 유형의 기본값으로 설정 된다는 사실에 의존 합니다. 귀하의 경우, 기본 값은 int이다 0정확하게 당신이 원하는이다.
UPD . C # 7.0부터이 스 니펫은 다음을 사용하여 단축 할 수 있습니다 out variables.
// declare variable right where it's passed
someDictionary.TryGetValue(id, out var currentCount);
someDictionary[id] = currentCount + 1;
읽기 쉽고 의도가 명확합니다. 괜찮다고 생각합니다. 더 똑똑하거나 더 짧은 코드를 발명 할 필요가 없습니다. 초기 버전만큼 명확하게 의도를 유지하지 않으면 :-)
즉, 다음은 약간 더 짧은 버전입니다.
public void IncrementCount(Dictionary<int, int> someDictionary, int id)
{
if (!someDictionary.ContainsKey(id))
someDictionary[id] = 0;
someDictionary[id]++;
}
사전에 동시에 액세스 할 수있는 경우 사전에 대한 액세스를 동기화해야합니다.
다음은 멋진 확장 방법입니다.
public static void Increment<T>(this Dictionary<T, int> dictionary, T key)
{
int count;
dictionary.TryGetValue(key, out count);
dictionary[key] = count + 1;
}
용법:
var dictionary = new Dictionary<string, int>();
dictionary.Increment("hello");
dictionary.Increment("hello");
dictionary.Increment("world");
Assert.AreEqual(2, dictionary["hello"]);
Assert.AreEqual(1, dictionary["world"]);
정수 키에 대한 .NET 4의 일부 측정입니다.
귀하의 질문에 대한 대답은 아니지만 완전성을 위해 정수 키를 기반으로 정수를 증가시키는 데 유용한 다양한 클래스의 동작을 측정했습니다. simple Array, Dictionary(@Ani의 접근 방식), Dictionary(단순한 접근 방식), SortedDictionary(@Ani의 접근 방식) ) 및 ConcurrentDictionary.TryAddOrUpdate.
다음은 직접 사용하는 대신 클래스로 래핑하기 위해 2.5ns로 조정 된 결과입니다.
Array 2.5 ns/inc
Dictionary (@Ani) 27.5 ns/inc
Dictionary (Simple) 37.4 ns/inc
SortedDictionary 192.5 ns/inc
ConcurrentDictionary 79.7 ns/inc
And that's the code.
Note that ConcurrentDictionary.TryAddOrUpdate is three times slower than Dictionary's TryGetValue + indexer's setter. And the latter is ten times slower than Array.
So I would use an array if I know the range of keys is small and a combined approach otherwise.
Here is a handy unit test for you to play with concerning ConcurrentDictionary and how to keep the values threadsafe:
ConcurrentDictionary<string, int> TestDict = new ConcurrentDictionary<string,int>();
[TestMethod]
public void WorkingWithConcurrentDictionary()
{
//If Test doesn't exist in the dictionary it will be added with a value of 0
TestDict.AddOrUpdate("Test", 0, (OldKey, OldValue) => OldValue+1);
//This will increment the test key value by 1
TestDict.AddOrUpdate("Test", 0, (OldKey, OldValue) => OldValue+1);
Assert.IsTrue(TestDict["Test"] == 1);
//This will increment it again
TestDict.AddOrUpdate("Test", 0, (OldKey, OldValue) => OldValue+1);
Assert.IsTrue(TestDict["Test"] == 2);
//This is a handy way of getting a value from the dictionary in a thread safe manner
//It would set the Test key to 0 if it didn't already exist in the dictionary
Assert.IsTrue(TestDict.GetOrAdd("Test", 0) == 2);
//This will decriment the Test Key by one
TestDict.AddOrUpdate("Test", 0, (OldKey, OldValue) => OldValue-1);
Assert.IsTrue(TestDict["Test"] == 1);
}
참고URL : https://stackoverflow.com/questions/7132738/incrementing-a-numerical-value-in-a-dictionary
'Nice programing' 카테고리의 다른 글
| 정규식 범위의 이스케이프 점 (0) | 2020.11.19 |
|---|---|
| Express Passport (node.js) 오류 처리 (0) | 2020.11.19 |
| 왜 std :: optional (0) | 2020.11.18 |
| DLL을 만들 때 모든 기호 내보내기 (0) | 2020.11.18 |
| SQL Server 2008 Developer를 설치할 때 사용할 계정 (0) | 2020.11.18 |