返回特定键的任何值的二值字典

发布于 2024-09-24 16:22:33 字数 213 浏览 4 评论 0 原文

我需要创建一个字典,每个键有 2 个值,并且它必须以相同的概率返回这 2 个值之一。

例子:

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

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

I need to create a dictionary that has 2 values per key, and it must return one of the 2 values with the same probability.

Example:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

想你的星星会说话 2024-10-01 16:22:33

可以编写一个以这种方式运行的 IDictionary 实现,但这不是一个好主意:大多数人会为集合类找到一个非确定性索引器非常不直观。

相反,我建议您将此作为键的的责任,而不是字典本身。一种选择是编写一个自定义类型,能够以相同的概率从一组可能性中进行选择。例如:

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();

It would be possible to write an IDictionary<TKey, TValue> implementation that behaved in this manner, but that would not be a good idea: most people would find a non-deterministic indexer for a collection-class very unintuitive.

Instead, I suggest you make this the responsibility of the value for a key, rather than the Dictionary itself. One option would be to write a custom-type that is capable of picking from a set of possibilities with equal probability. For example:

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)];
    }
}

You could then use the dictionary like this:

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

int randomValueFromA = dict["A"].GetRandomValue();
梦萦几度 2024-10-01 16:22:33

框架中没有内置任何内容来执行此操作,但您可能希望通过创建一个具有 Dictionary> 的“包装”类型来实现它。然后,您可以编写一个索引器来在两个值之间进行适当的选择。

There's nothing built into the framework to do this, but you'd probably want to implement it by creating a "wrapper" type which had a Dictionary<TKey, Tuple<TValue, TValue>>. You'd then write an indexer to choose appropriately between the two values.

小清晰的声音 2024-10-01 16:22:33

实际上,我只是在一个内部使用 Dictionary 的类中实现它。这样,您甚至可以实现该类型以使每个键具有可变数量的值。

喜欢:

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;
    }
}

I would actually just implement this in a class that uses a Dictionary<TKey, TValue[]> internally. That way you could even implement the type to have a variable number of values per key.

Like:

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;
    }
}
我为君王 2024-10-01 16:22:33

使用 Tuple 作为字典值类型。

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

Use Tuple as dictionary value type.

IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
// ...
int secondValue = doubleDictionary["A"].Item2;
眼角的笑意。 2024-10-01 16:22:33

您还可以为字典编写一个扩展方法,这样您就可以创建如下内容:

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
}

^^这是我写的,所以如果有轻微错误,请原谅。

You could also write an extension method for the dictionary, so you could create something like this:

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


doubleDictionary.GetRandomValueForKey("A");

Then you can use this with any dictionary.

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

^^ that was written off the top of my head, so please excuse me if this is slightly wrong.

苦笑流年记忆 2024-10-01 16:22:33

下面的代码将解决问题的字典部分,并使随机化可定制,以便您可以应用适合您需求的伪随机级别。 (或者简单地对其进行硬编码而不是使用函子)

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();
    }
}

This below code will solve the dictionary part of the problem and make the randomization customizable so that you can apply a level so pseudo-randomness that suits your needs. (or simply hard code it instead of the use of a functor)

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文