Home > Blockchain >  Creating Dictionary<Enum, int> from Enum
Creating Dictionary<Enum, int> from Enum

Time:01-02

As a project I'm creating a poker game.

I have an array of Cards, each of which has a value CardValue given by the enum below. I want a dictionary Dictionary<CardValue, int> to contain the number of occurences of each CardValue in the array of Cards.

public enum CardValue
{
    Ace = 1,
    Two = 2,
    Three = 3,
    Four = 4,
    Five = 5,
    Six = 6,
    Seven = 7,
    Eight = 8,
    Nine = 9,
    Ten = 10,
    Jack = 11,
    Queen = 12,
    King = 13
}

I have created this dictionary manually, and it only has thirteen key value pairs so wasn't too expensive... but if I had a far larger enum I would want a more efficient way to create this dictionary (from a quick scan of the web you can use ToDictionary() for IEnumarables, but not sure if relevant).

Note for question similarity: This got flagged for being too similar to:

Enum to Dictionary<int, string> in C#

However in this question they had a dictionary of type Dictionary<int, string> whereas I want to retain the enum in the key of the dictionary for referencing purposes, and don't want this replaced by an int. E.g. For checking the number of queens that occur in an array of cards I want to check CardValueCount[CardValue.Queen] and not CardValueCount[12] for readability.

The code I have at the moment is here (edit: removed switch statement as suggested):

    public Card[] Cards {get; set;}
    private Dictionary <CardValue, int> CardValueCount
    {
        get
        {
            var cardValueCount = new Dictionary<CardValue, int>()
            {
                { CardValue.Ace, 0},
                { CardValue.Two, 0},
                { CardValue.Three, 0},
                { CardValue.Four, 0},
                { CardValue.Five, 0},
                { CardValue.Six, 0},
                { CardValue.Seven, 0},
                { CardValue.Eight, 0},
                { CardValue.Nine, 0},
                { CardValue.Ten, 0},
                { CardValue.Jack, 0},
                { CardValue.Queen, 0},
                { CardValue.King, 0}
            };
            if (Cards.Length < 1 || Cards == null)
            {
                return cardValueCount;
            }
            else
            {
                foreach (Card card in Cards)
                {
                    cardValueCount[card.Value]  ;
                }
                return cardValueCount;
            }
        }
    }

(Edit 2) Removed switch statement as suggested.

Note 1: Haven't actually ran this yet so there may be something that wouldn't work as is!

CodePudding user response:

You can get an array with all the values of the CardValue enumeration, with the static method Enum.GetValues.

// Retrieves an array of the values of the constants in a specified enumeration.
public static Array GetValues (Type enumType);

The array is untyped, so you have to cast each value to CardValue.

Usage example:

Dictionary<CardValue, int> dict = new();
foreach(CardValue x in Enum.GetValues(typeof(CardValue)))
    dict.Add(x, 0);

...or using LINQ:

Dictionary<CardValue, int> dict = Enum.GetValues(typeof(CardValue))
    .Cast<CardValue>()
    .ToDictionary(x => x, x => 0);

Online demo.

CodePudding user response:

Resuing the @Theodor's answer.

you could use the GroupBy and Count method in the else part.

private Dictionary<CardValue, int> CardValueCount
{
    get
    {
        if (Cards.Length < 1 || Cards == null)
        {
            return Enum.GetValues(typeof(CardValue))
                .Cast<CardValue>()
                .ToDictionary(x => x, x => 0);
        }
        else
        {
            return Cards.GroupBy(card => card.Value)
                .ToDictionary(group => group.Key, group => group.Count());
        }
    }
}

CodePudding user response:

You can build a Dictionary from an Enumerable of KeyValuePairs, and you can get that by transforming an array of the names of each CardValue back into the enum representation.

var cardValueCount = new Dictionary<CardValue, int>(
    Enum.GetNames(typeof(CardValue)).Select(t =>
      new KeyValuePair<CardValue, int>(CardValue.Parse<CardValue>(t), 0))
  );
  • Related