2010-09-26 56 views
2

我需要創建一個字典,每個鍵有2個值,它必須以相同的概率返回2個值之一。雙值字典返回任何一個特定的鍵的值

例子:

myDicry 
{ 
    key = "A", value1=15, value2=56; 
} 

int firstCall = myDicry["A"]; // = 15 
int secondCall = myDicry["A"]; // = 56 
+0

有趣的問題..你能一點就可以了擴大? – 2010-09-26 17:55:01

+0

當查找某個鍵時,它是否總是先返回第一個值,然後是第二個還是應該是隨機的(這不違反概率要求)? – NullUserException 2010-09-26 17:56:37

回答

1

我真的只是實現這個在使用Dictionary<TKey, TValue[]>內部類。這樣你甚至可以實現這個類型,每個鍵的值都是可變的。

像:

class RandomDictionary<TKey, TValue> 
{ 
    Dictionary<TKey, TValue[]> m_dict; 
    Random m_random; 

    public RandomDictionary() 
    { 
     m_dict = new Dictionary<TKey, TValue[]>(); 
     m_random = new Random(); 
    } 

    public TValue this[TKey key] 
    { 
     get 
     { 
      TValue[] values = m_dict[key]; 
      return values[m_random.Next(0, values.Length)]; 
     } 
    } 

    public void Define(TKey key, params TValue[] values) 
    { 
     m_dict[key] = new TValue[values.Length]; 
     Array.Copy(values, m_dict[key], values.Length); 
    } 

    public bool TryGetValue(TKey key, out TValue value) 
    { 
     TValue[] values; 
     if (!m_dict.TryGetValue(key, out values)) 
     { 
      value = default(TValue); 
      return false; 
     } 

     value = values[m_random.Next(0, values.Length)]; 
     return true; 
    } 
} 
7

沒有什麼內置的框架,以做到這一點的,但你可能會希望通過創建有Dictionary<TKey, Tuple<TValue, TValue>>「包裝」類來實現它。然後你會寫一個索引器在這兩個值之間進行適當的選擇。

+0

這就是我想要建議的,但我被打敗了。 – jimplode 2010-09-26 17:59:51

+0

@jimplode你不能擊敗Skeet – 2010-09-26 18:18:24

+1

@Skeet:總會有下次! ;) – jimplode 2010-09-26 18:19:21

0

使用元組作爲字典值類型。

IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>(); 
// ... 
int secondValue = doubleDictionary["A"].Item2; 
+0

「當查找某個鍵時,它是否總是首先返回第一個值,然後是第二個還是應該是隨機的?」 NO =) – ZAA 2010-09-26 17:59:33

+0

仍然需要一些工作來切換值。 – 2010-09-26 18:00:13

+0

要BlueCode:沒有好處,因爲它必須隨機r without沒有.item1或item2 – ZAA 2010-09-26 18:01:53

0

你也可以寫一個擴展方法的字典,所以你可以創建這樣的事情:

IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>(); 


doubleDictionary.GetRandomValueForKey("A"); 

然後,你可以用任何字典使用。

public static void GetRandomValueForKey(this Dictionary<string, Tuple<int, int>> dict, 
            string key) 
{ 
    ... Code to return the value 
} 

^^這是從我頭頂上寫下來的,所以請原諒,如果這有點不對勁。

9

有可能編寫一個以這種方式運行的IDictionary<TKey, TValue>實現,但這不是一個好主意:大多數人會發現集合類的非確定性索引器非常不直觀。

取而代之的是,我建議您將這個值作爲的責任,而不是字典本身。一種選擇是編寫一種能夠以相同的概率從一組可能性中挑選的自定義類型。例如:

public class UnbiasedRandomPicker<T> 
{ 
    private readonly Random _rand = new Random(); 
    private readonly T[] _possibilities; 

    public UnbiasedRandomPicker(params T[] possibilities) 
    { 
     // argument validation omitted 
     _possibilities = possibilities; 
    } 

    public T GetRandomValue() 
    { 
     return _possibilities[_rand.Next(_possibilities.Length)]; 
    } 
} 

然後,您可以使用字典是這樣的:

var dict = new Dictionary<string, UnbiasedRandomPicker<int>> 
{ 
    {"A", new UnbiasedRandomPicker<int>(15, 56)}, 
    {"B", new UnbiasedRandomPicker<int>(25, 13)} 
}; 

int randomValueFromA = dict["A"].GetRandomValue(); 
+0

謝謝,我認爲這對我來說是更好的解決方案! – ZAA 2010-09-26 19:08:30

0

這下面的代碼就能解決問題的字典部分,使隨機化定製,使您可以應用水平,使僞隨機性,適合您的需求。 (或者乾脆硬編碼,而不是使用函子)

public class DoubleDictionary<K, T> : IEnumerable<KeyValuePair<K, T>> 
{ 
    private readonly Dictionary<K, Tuple<T, T>> _dictionary = new Dictionary<K, Tuple<T, T>>(); 
    private readonly Func<bool> _getFirst; 

    public DoubleDictionary(Func<bool> GetFirst) { 
     _getFirst = GetFirst; 
    } 

    public void Add(K Key, Tuple<T, T> Value) { 
     _dictionary.Add(Key, Value); 
    } 

    public T this[K index] { 
     get { 
      Tuple<T, T> pair = _dictionary[index]; 
      return GetValue(pair); 
     } 
    } 

    private T GetValue(Tuple<T, T> Pair) { 
     return _getFirst() ? Pair.Item1 : Pair.Item2; 
    } 

    public IEnumerable<K> Keys { 
     get { 
      return _dictionary.Keys; 
     } 
    } 

    public IEnumerable<T> Values { 
     get { 
      foreach (var pair in _dictionary.Values) { 
       yield return GetValue(pair); 
      } 
     } 
    } 

    IEnumerator<KeyValuePair<K, T>> IEnumerable<KeyValuePair<K, T>>.GetEnumerator() { 
     foreach (var pair in _dictionary) { 
      yield return new KeyValuePair<K, T>(pair.Key, GetValue(pair.Value)); 
     } 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { 
     return ((IEnumerable<KeyValuePair<K, T>>)this).GetEnumerator(); 
    } 
} 
相關問題