2


0

特定のキーの値のいずれかを返す2値辞書

キーごとに2つの値を持つ辞書を作成する必要があり、同じ確率で2つの値のいずれかを返す必要があります。

例:

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

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

6 Answer


9


このように動作する「IDictionary」実装を作成することは可能ですが、それは良い考えではありません。ほとんどの人は、コレクションクラスの非決定的なインデクサーを非常に直感的ではないでしょう。

代わりに、辞書自体ではなく、これをキーの_value_の責任にすることをお勧めします。 1つのオプションは、同じ確率で一連の可能性から選択できるカスタムタイプを記述することです。 例えば:

public class UnbiasedRandomPicker
{
    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>
{
    {"A", new UnbiasedRandomPicker(15, 56)},
    {"B", new UnbiasedRandomPicker(25, 13)}
};

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


7


これを行うためのフレームワークには何も組み込まれていませんが、おそらく `Dictionary>`を持つ「ラッパー」タイプを作成して実装することをお勧めします。 次に、2つの値から適切に選択するインデクサーを作成します。


1


私は、実際にこれを内部で `Dictionary`を使用するクラスに実装します。 そうすれば、キーごとに可変数の値を持つタイプを実装することもできます。

好きです:

class RandomDictionary
{
    Dictionary m_dict;
    Random m_random;

    public RandomDictionary()
    {
        m_dict = new Dictionary();
        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;
    }
}


0


辞書の値の型としてタプルを使用します。

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


0


辞書の拡張メソッドを書くこともできますので、次のようなものを作成できます。

IDictionary> doubleDictionary = new Dictionary>();


doubleDictionary.GetRandomValueForKey("A");

次に、これを任意の辞書で使用できます。

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

^^これは私の頭のてっぺんから書かれたものなので、これが少し間違っている場合はご容赦ください。


0


以下のコードは、問題の辞書部分を解決し、ランダム化をカスタマイズ可能にして、ニーズに合った擬似ランダム性を適用できるようにします。 (またはファンクターを使用する代わりに単純にハードコーディングする)

public class DoubleDictionary : IEnumerable>
{
    private readonly Dictionary> _dictionary = new Dictionary>();
    private readonly Func _getFirst;

    public DoubleDictionary(Func GetFirst) {
        _getFirst = GetFirst;
    }

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

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

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

    public IEnumerable Keys {
        get {
            return _dictionary.Keys;
        }
    }

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

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

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return ((IEnumerable>)this).GetEnumerator();
    }
}