1

I am trying to implement random entry from dictionary function regarded here into unity3d in visual studio : Random entry from dictionary .

private void somefunction() {

            Dictionary<string, Sprite> dict = (Dictionary<string, Sprite>) RandomValues(slotImages).Take(5);

            foreach (KeyValuePair<string, Sprite> keyValue in dict)
            {
                Debug.Log("random slotImages name : " + keyValue.Key); 
            }

}
public IEnumerable<TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict)
    {
        System.Random rand = new System.Random();
        List<TValue> values =  Enumerable.ToList(dict.Values);
        int size = dict.Count;
        while (true)
        {
            yield return values[rand.Next(size)];
        }
    }

But I am having following error ;

InvalidCastException: cannot cast from source type to destination type.
Alp
  • 1,863
  • 1
  • 20
  • 38
  • `RandomValues` returns an `IEnumerable`, which you're trying to cast into a `Dictionary`. There is no simple cast for that - what exactly do you want the dictionary to contain? – Frauke May 11 '19 at 23:24
  • @FraukeNonnenmacher I want dictionary to contain (Dictionary dict) name of the image and the image, example:"apple" and apple.png – Alp May 11 '19 at 23:27
  • So where should the name of the image come from? Is it the key from slotImages? In that case, wouldn't it be easier to simply pick some random entries from the dictionary you pass into `RandomValues` instead of trying to convert it to an `IEnumerable` and back again? – Frauke May 11 '19 at 23:30
  • @FraukeNonnenmacher , image and name coming from seperate resources. Yes its the key. I am trying to pick some random entries from dictionary the best way possible. – Alp May 11 '19 at 23:36
  • Ah, I see. Unfortunately the example you've followed will only give you random **values** from the dictionary, not random entries. Let me see if I can find something... – Frauke May 11 '19 at 23:38
  • 1
    Am I correct to assume that your resulting collection should not contain the same sprite multiple times? A Dictionary can't contain the same key twice, but it looks like you're doing some kind of slot machine, in which case you may want duplicates... – Frauke May 12 '19 at 00:15
  • @FraukeNonnenmacher yes – Alp May 12 '19 at 00:17

1 Answers1

3

The code you currently have in RandomValues returns a list of random values from the dictionary, not actual dictionary entries, i.e. key/value pairs. Essentially you're trying to cast an IEnumerable to a Dictionary, which can't be done implicitly.

The following code should do what you want:

public IDictionary<TKey, TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict, int count)
{
    if (count > dict.Count || count < 1) throw new ArgumentException("Invalid value for count: " + count);

    Random rand = new Random();

    Dictionary<TKey, TValue> randDict = new Dictionary<TKey, TValue>();
    do
    {
        int index = rand.Next(0, dict.Count);
        if (!randDict.ContainsKey(dict.ElementAt(index).Key))
            randDict.Add(dict.ElementAt(index).Key, dict.ElementAt(index).Value);
    } while (randDict.Count < count);

    return randDict;
}

Please note that you now need to pass in the number of entries you want as an argument. The return value will be a dictionary with count random, unique entries from the original.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Frauke
  • 1,552
  • 2
  • 12
  • 22