2011-12-10 193 views
7

我有一個字典與雙打值和字符串作爲關鍵。如何統計Dictionary中唯一值的出現次數?

我想統計本詞典中每個值的出現次數,我想知道這個值(例如重複)。

例如:

key1, 2 
key2, 2 
key3, 3 
key4, 2 
key5, 5 
key6, 5 

我希望得到一個列表:

2 - 3 (times) 
3 - 1 (once) 
5 - 2 (twice) 

我該怎麼辦呢?

+1

多一點信息:您詢問不重複的值的計數?你能給我們一個數據的例子,以及你想要的輸出嗎? – Alan

+5

爲平等測試雙打是一個非常可疑的做法。如果你想得到答案,你可能想避免提及它。在Values屬性中使用Linq的Distinct()。Count()可以很好地匹配你的標籤。 –

+2

你想在這裏測試雙打的平等嗎? –

回答

9

首先要注意的是,你實際上並不關心字典的關鍵字。因此,第一步是忽視它們與手頭任務無關。我們將使用字典的Values屬性,並且該工作與任何其他整數集合(或者任何其他可比較的平等類型的枚舉)的工作大致相同。

這個問題有兩種常見的方法,兩者都值得了解。

首先使用另一個字典保存值的計數:

//Start with setting up the dictionary you described. 
Dictionary<string, int> dict = new Dictionary<string, int>{ 
    {"key1", 2}, 
    {"key2", 2}, 
    {"key3", 3}, 
    {"key4", 2}, 
    {"key5", 5}, 
    {"key6", 5} 
}; 
//Create a different dictionary to store the counts. 
Dictionary<int, int> valCount = new Dictionary<int, int>(); 
//Iterate through the values, setting count to 1 or incrementing current count. 
foreach(int i in dict.Values) 
    if(valCount.ContainsKey(i)) 
     valCount[i]++; 
    else 
     valCount[i] = 1; 
//Finally some code to output this and prove it worked: 
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed 
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value); 

但願這是非常簡單的。另一種方法是比較複雜,但有一些長處:

//Start with setting up the dictionary you described. 
Dictionary<string, int> dict = new Dictionary<string, int>{ 
    {"key1", 2}, 
    {"key2", 2}, 
    {"key3", 3}, 
    {"key4", 2}, 
    {"key5", 5}, 
    {"key6", 5} 
}; 
IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x); 
//Two options now. One is to use the results directly such as with the 
//equivalent code to output this and prove it worked: 
foreach(IGrouping<int, int> item in grp)//note - not sorted, that must be added if needed 
    Console.WriteLine("{0} - {1}", item.Key, item.Count()); 
//Alternatively, we can put these results into another collection for later use: 
Dictionary<int, int> valCount = grp.ToDictionary(g => g.Key, g => g.Count()); 
//Finally some code to output this and prove it worked: 
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed 
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value); 

(我們可能會使用var而不是冗長IEnumerable<IGrouping<int, int>>,但它是值得向大家解釋代碼時是準確的)。

在直截了當的比較中,這個版本更差 - 理解更復雜,效率更低。然而,學習這種方法可以爲同一技術提供一些簡潔而有效的變體,因此值得研究。

GroupBy()接受一個枚舉並創建另一個包含鍵值對的枚舉,其中的值也是一個枚舉。 lambda x => x意味着它是按其自身分組的,但我們對不同分組規則的靈活性不止於此。的grp內容看起來有點像:

{ 
    {Key=2, {2, 2, 2}} 
    {Key=3, {3}} 
    {Key=5, {5, 5}} 
} 

所以,如果我們遍歷這個的每一個我們拉出Key和組呼Count()組,我們得到我們想要的結果。

現在,在第一種情況下,我們在單個O(n)通道中構建了我們的計數,而在此我們通過O(n)通道構建該組,然後在第二個O(n )通過,使其效率低得多。這也有點難以理解,爲什麼要提起它呢?

好,第一是,一旦我們這樣做的理解,我們可以把線:

IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x); 
foreach(IGrouping<int, int> item in grp) 
    Console.WriteLine("{0} - {1}", item.Key, item.Count()); 

分爲:

foreach(var item in dict.Values.GroupBy(x => x)) 
    Console.WriteLine("{0} - {1}", item.Key, item.Count()); 

這是相當簡潔,併成爲習慣。如果我們希望繼續下去,並採用值計數對做更復雜的事情,那我們就可以將其鏈接到另一個操作中,這一點尤其好。

是把結果放到一個字典版本可以更加簡潔還是:

var valCount = dict.Values.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count()); 

在那裏,你的整個問題在一個短線回答,而不是6(切割評論)首版。 (有些人可能更喜歡用dict.GroupBy(x => x.Value)替換dict.Values.GroupBy(x => x),如果你不確定爲什麼,就試着去解決),如果你不確定爲什麼,就會得到完全相同的結果。

另一個好處是,在其他情況下,我們有更多的靈活性,GroupBy。由於這些原因,習慣使用GroupBy的人很可能以dict.Values.GroupBy(x => x).ToDictinary(g => g.Key, g => g.Count());的單行簡明開始,然後轉變爲第一版本的更詳細但更有效的形式(其中我們增加了新字典中的總計數)如果它證明了性能熱點。

-1

即使簡單的將是:

Private Function CountOccurenceOfValue(dictionary As Dictionary(Of Integer, Integer), valueToFind As Integer) As Integer 
    Return (From temp In dictionary Where temp.Value.Equals(valueToFind) Select temp).Count() 
End Function 

(是的,它是在VB.NET,但你不應該有太大的麻煩,轉換爲C#:-))

+0

用戶正在詢問C#,因此答案應該用C#表示。 – Neeko

相關問題