我需要创建一个字典,每个键有2个值,它必须以相同的概率返回2个值之一。双值字典返回任何一个特定的键的值
例子:
myDicry
{
key = "A", value1=15, value2=56;
}
int firstCall = myDicry["A"]; // = 15
int secondCall = myDicry["A"]; // = 56
我需要创建一个字典,每个键有2个值,它必须以相同的概率返回2个值之一。双值字典返回任何一个特定的键的值
例子:
myDicry
{
key = "A", value1=15, value2=56;
}
int firstCall = myDicry["A"]; // = 15
int secondCall = myDicry["A"]; // = 56
我真的只是实现这个在使用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;
}
}
使用元组作为字典值类型。
IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
// ...
int secondValue = doubleDictionary["A"].Item2;
你也可以写一个扩展方法的字典,所以你可以创建这样的事情:
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
}
^^这是从我头顶上写下来的,所以请原谅,如果这有点不对劲。
有可能编写一个以这种方式运行的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();
谢谢,我认为这对我来说是更好的解决方案! – ZAA 2010-09-26 19:08:30
这下面的代码就能解决问题的字典部分,使随机化定制,使您可以应用水平,使伪随机性,适合您的需求。 (或者干脆硬编码,而不是使用函子)
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();
}
}
有趣的问题..你能一点就可以了扩大? – 2010-09-26 17:55:01
当查找某个键时,它是否总是先返回第一个值,然后是第二个还是应该是随机的(这不违反概率要求)? – NullUserException 2010-09-26 17:56:37