2013-04-05 21 views
0

假設我需要增加一個條目的ValueDictionary,如:如何僅使用單個鍵查找來更改字典條目?

public void Increment(string key, int increment) 
{ 
    m_dict[key] += increment; 
} 

而且還假設我需要使其工作時,有對key沒有條目,如:

public void Increment(string key, int increment) 
{ 
    if (m_dict.ContainsKey(key)) 
    { 
     m_dict[key] += increment; 
    } 
    else 
    { 
     m_dict[key] = increment; 
    } 
} 

有沒有辦法將key查找的數量減少到一個?

我能想到的最好的解決方法是以下,這是一個有點笨重,使用兩個查找:

public void Increment(string key, int increment) 
{ 
    long value; 
    if (m_dict.TryGetValue(key, out value)) 
    { 
     m_dict[key] = value + increment; 
    } 
    else 
    { 
     m_dict.Add(key, increment); 
    } 
} 
+3

這是你可以得到的最好的。 – 2013-04-05 13:03:01

+0

爲什麼不使用第二個代碼塊並用'm_dict.Add(key,increment)'替換'm_dict [key] = increment'? – 2013-04-05 13:08:45

+0

@JohnWillemse因爲在第一種情況下這仍然是三次查找。一個用於'ContainsKey'和兩個用於'+ =',我猜。 – LumpN 2013-04-08 08:42:58

回答

1

我不能肯定是否只做引擎蓋下的一個查找,但ConcurrentDictionary有一個AddOrUpdate方法,它具有您正在查找的行爲,但正如我所說的,我無法確定查找的數量。

請參見:http://msdn.microsoft.com/en-gb/library/ee378675.aspx

而且,我相信字典有自動AddOrUpdate行爲:

_dict["key"] = 12總會發生變異或取決於它是否已經存在增加。

+1

'AddOrUpdate'正是我所需要的。太糟糕了,沒有'Dictionary'這樣的東西。 item訪問器'this [TKey key]'實際上更像'AddOrReplace'。 – LumpN 2013-04-08 08:45:38

1

你可以使用類似的東西。

public class Holder { 
    public long Value { get; set; } 
} 

public void Increment(Dictionary<string, Holder> dict, string key, int increment) { 
     Holder box; 
     if(dict.TryGetValue(key, out box)) box.Value += increment; 
     else { 
      dict[key] = new Holder { 
       Value = increment 
      }; 
     } 
    } 

包裝類對性能沒有明顯影響,因爲這幾乎等於boxin/unboxing已經發生(我認爲)。

我做了一個小測試,性能似乎更好,您必須確認在所有用例中的性能是否更好。

[Fact] 
     public void benchmark_dictionary() { 
      var dictionary = new Dictionary<string, long> { 
       {"a", 1}, 
       {"b", 2}, 
       {"c", 3} 
      }; 

      var dictionary2 = new Dictionary<string, Holder> { 
       { 
        "a", new Holder() { 
         Value = 1 
        } 
       }, { 
        "b", new Holder() { 
         Value = 2 
        } 
       }, { 
        "c", new Holder() { 
         Value = 3 
        } 
       } 
      }; 

      var iterations = 1000000; 
      var timer = new Stopwatch(); 
      timer.Start(); 
      for(int i = 0; i < iterations; i++) 
       Increment(dictionary, "a", 1); 
      timer.Stop(); 

      // DumpOnConsole() -> Console.WriteLine(objetc) 
      timer.ElapsedMilliseconds.DumpOnConsole(); 

      dictionary.DumpOnConsole(); 

      timer.Restart(); 

      for(int i = 0; i < iterations; i++) 
       Increment(dictionary2, "a", 1); 
      timer.Stop(); 

      timer.ElapsedMilliseconds.DumpOnConsole(); 

      dictionary2.DumpOnConsole(); 
     } 

問候。

+0

我喜歡'Holder'如何將查找次數減少到1,以防鑰匙已經在字典中。 – LumpN 2013-04-08 08:40:07

相關問題