2012-10-01 16 views
0

我正在實現一個擴展方法,返回TKeyIDictionary<TKey, TValue>作爲參數。如果TValuedouble,該方法很可能返回具有最高值的TKey。否則,它會隨機返回一個TKeyLinq重載where子句排除特定類型

public static TKey Sample<TKey>(this IDictionary<TKey, double> probabilityTable, Random r) 
    { 
     probabilityTable.Normalize(); 

     var roll = r.NextDouble(); 
     var temp = 0.0; 
     foreach (var key in probabilityTable.Keys) 
     { 
      temp += probabilityTable[key]; 
      if (roll <= temp) 
       return key; 
     } 

     return default(TKey); 
    } 

    public static TKey Sample<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Random r) 
    { 
     return dictionary.Skip(r.Next(dictionary.Count)).FirstOrDefault().Key; 
    } 

    public static IDictionary<TKey, double> Normalize<TKey>(this IDictionary<TKey, double> probabilityTable) 
    { 
     if (probabilityTable.Any(x => x.Value < 0)) 
      throw new ArgumentOutOfRangeException("probabilityTable", "Probability is expected to be positive."); 

     var sum = probabilityTable.Sum(x => x.Value); 

     if (Math.Abs(sum - 1) > 1e-8) 
      return probabilityTable.ToDictionary(x => x.Key, x => x.Value/sum); 

     if (Math.Abs(sum) < 1e-8) 
      return probabilityTable.ToDictionary(x => x.Key, x => 1.0/probabilityTable.Count); 

     return probabilityTable; 
    } 

的問題是,Sample<TKey, TValue>始終即使有TValuedouble調用。任何方式,我可以指定類型TValue排除雙where子句?即where TValue: !double

調用擴展函數的代碼如下:

 var r = new Random(); 
     var pt = new Dictionary<char, double> {{'A', 0.1}, {'B', 0.2}, {'C', 0.7}}; 
     var ct = new Dictionary<char, char> {{'A', 'D'}, {'B','E'}, {'C', 'F'}}; 
     Console.WriteLine(pt.Sample(r)); // expected to return 'C' mostly but uniformly returns key 
     Console.WriteLine(ct.Sample(r)); 
+0

如果我運行這個代碼(取出調用'Normalize',這裏沒有顯示)我得到了'double'和'char'的期望分佈。也許你的'Normalize'方法壞了? – Rawling

+0

@Rawling對不起,這只是一個適用於cateogrical發佈的規範化方法。我添加了它。 –

回答