2014-07-11 16 views
0

我有以下情形:我應該如何「合併」多個詞典到C#中的「聚合」?

GetDict()返回Dictionary<double, double>對象和在一個循環中被稱爲若干次(由用戶指定的這個數)的函數。返回的字典總是保證包含相同的一組鍵(我現在假設這是簡單的)。

我的目標是最終讓所有的值的平均值爲每個鍵返回:

public Dictionary<double, double> CalculateAveragePerKey(int N) 
{ 
    var aggregateDict = new Dictionary<double, double>(); 

    for(int i=0; i < N; i++) 
    { 
     var returnedDict = GetDict(); 
     // aggregateDict -- how to calculate an average of values for each key? 
    } 

    return aggregateDict; 
} 

public Dictionary<double, double> GetDict() 
{ 
    var newDict = new Dictionary<double, double>(); 
    // populate the newDict, always guaranteed (assumed for simplicity) 
    // to contain the same set of keys ... 
    return newDict; 
} 

所以,如果N = 3和內環路,詞典返回包含該鍵10.01.02.33.0,結尾aggregateDict的密鑰10.0的值應該爲2.1

如果這不是解決這類問題的最好的數據結構或方法,我肯定可以重構我的代碼以使用其他數據結構或方法。我只是在尋找最有效的方法。

+0

'double'是用於字典的關鍵字的一種非常糟糕的類型,因爲浮點精度錯誤通常會導致您希望相等的數字不相等,再加上基於哈希的結構不符合這一事實, t'確實處理模糊的平等。 – Servy

+0

我沒有想到這一點。那麼我還能怎麼解決這個問題呢?我應該使用二維數組來存儲鍵值對嗎? (我也可以在預處理過程中將我的密鑰投射到GetDict()中,但是有更好的選擇嗎?) – ubuntunoob

+0

這是功課嗎?你有沒有試圖自己解決這個問題? – MgSam

回答

1

您可以通過修改代碼來計算平均分兩個步驟:

  • 當你在一個循環中調用GetDict(),經過它的鑰匙,當環路是增加值的aggregateDict
  • 值結束,再次檢查值,並將它們除以N

您可以通過N環內還劃分的GetDict()值,這取決於價值觀,你在GetDict()得到分配。

您還可以使用LINQ做到這一點,而無需使用一個循環,這樣的:

var avg = Enumerable 
    .Range(0, N) 
    .SelectMany(n => GetDict()) 
    .GroupBy(p => p.Key) 
    .ToDictionary(
      g => g.Key 
     , g => g.Sum(p => p.Value)/g.Count() 
     ); 

請注意,您需要使用double當作爲字典鍵,因爲浮點類型往往不太準確,要非常小心。結果,您可能會看到兩個非常接近的數字映射到不同的字典鍵。

+0

謝謝,我正在考慮重寫一些邏輯來將我的密鑰投入整數。後續問題 - 我的數據集包含大約30k個鍵值對。 LINQ是最有效的方法嗎?我最初使用了你提到的循環全部值方法,但是想知道由於我的數據集的大小,它是否有效。 – ubuntunoob

+0

@ubuntunoob如果數字「N」等於或大於10,則使用您的方法(請參閱答案的頂部),因爲它使用較少的內存。就時間而言,無論你是否使用LINQ都沒有關係,因爲無論哪種方式,時間都是按照'K * N'的順序,其中'K'是鍵的數量,'N'是重複次數。不過,LINQ會傾向於使用更多的內存,所以對於高'N'你可能會更好一個循環。 – dasblinkenlight

+0

現在N是3或4.我將嘗試LINQ方法,謝謝。我已經讀了一些關於PLINQ的內容,但沒有使用它。它會幫助嗎? – ubuntunoob