2017-09-18 14 views
0

J'ai un peu un dictionnaire complexe.C#: moyen le plus simple d'initialiser et de remplir ce dictionnaire 2D/3D particulier?

Il est un dictionnaire qui contient deux types énumérés & une liste <>

Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary; 

Alors, quand je veux l'utiliser, je fais quelque chose comme ceci:

//Add "myString" to the List<string> 
myDictionary[BiomeType.Jungle][LocationType.City1].Add("myString")); 

Lorsque je tente d'ajouter "myString" à myList, il jette une erreur prévisible évidente &: "KeyNotFoundException: La clé donnée n'était pas présente dans le dictionnaire."

Est-il possible en C# d'avoir automatiquement le dictionnaire pour ajouter la clé si elle n'y est pas déjà? J'ai beaucoup de BiomeTypes & encore plus de LocationTypes. Ce serait un PITA de créer chaque liste, puis de créer chaque dictionnaire de type emplacement, puis de l'ajouter pour chaque BiomeType. Tout cela fonctionne juste pour initialiser ce dictionnaire complexe. N'y a-t-il pas un moyen facile de faire cela?

J'utilise cela pour gamedev, pour stocker des objets dans un dictionnaire, donc je peux y accéder en faisant quelque chose comme

BiomeType playerCurrentBiomeType; 
LocationType playerCurrentLocationType; 
LoadLevel(myDictionary[playerCurrentBiomeType][playerCurrentLocationType]); 

//ex. myDictionary[BiomeType.Jungle][LocationType.CapitalCity] 
//ex. myDictionary[BiomeType.Desert][LocationType.CapitalCity] 
//ex. myDictionary[BiomeType.Desert][LocationType.City3] 
+0

Il est évident que tout le monde pourrait facilement initialiser le dictionnaire de la manière normale en ajoutant tout simplement ligne par ligne. Cependant, comme je l'ai mentionné, c'est une énorme liste PITA qui crée une liste après la liste, puis crée de nouveaux dictionnaires peuplés par ces listes, puis finalement ajoute ces dictionnaires à l'autre dictionnaire. Juste vérifier s'il y a un moyen plus facile. – Carter81

+0

Je sais aussi que je ne pourrais tout simplement pas utiliser un seul dictionnaire pour tout conserver, et créer plutôt un seul dictionnaire pour chaque biome, ou quelque chose du genre. Cependant, j'ai aimé l'idée de simplement saisir tous les objets dans un seul conteneur en utilisant simplement BiomeType/LocationType. Semblait plus simple. – Carter81

+0

C# ne sait rien sur 'Dictionary', donc il n'y a pas de moyen plus simple. Vous devrez écrire du code pour le faire. –

Répondre

0

boucle simplement à travers tous les possibles type ENUM & ajouter une nouvelle valeur fonctionne pour remplir pleinement ce dictionnaire multidimensionnel. La solution de Robyn fonctionne de la même manière si vous ne voulez pas remplir entièrement le conteneur avec TOUTES les valeurs enum.

1

Peut-être, vous pouvez essayer ceci:

Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary = new Dictionary<BiomeType, Dictionary<LocationType, List<string>>>(); 

BiomeType playerCurrentBiomeType; 
LocationType playerCurrentLocationType; 

if(!myDictionary.ContainsKey(playerCurrentBiomeType)) 
{ 
    myDictionary.Add(playerCurrentBiomeType, new Dictionary<LocationType , List<string>>{{playerCurrentLocationType, new List<string>()}}); 
} 

myDictionary[playerCurrentBiomeType][playerCurrentLocationType].Add("bla"); 
1

Vous pourrait faire ceci (bien que pour être honnête je ne suis pas sûr que vous devriez!)

La classe ci-dessous est un type qui agit généralement comme un dictionnaire, fait ce que vous avez demandé, et a d'autres changements à cacher de vous les éléments vides qu'il crée chaque fois que vous demandez à l'indexeur pour un élément qui n'existe pas.

public class SmellyDictionary<T1, T2>: IDictionary<T1, T2>, ICollection where T2 : ICollection, new() 
{ 
    private readonly IDictionary<T1, T2> _dict = new Dictionary<T1, T2>(); 

    public T2 this[T1 key] 
    { 
     get 
     { 
      T2 value; 
      if (!_dict.TryGetValue(key, out value)) 
       _dict[key] = value = new T2(); // This stinks! 
      return value; 
     } 
     set { _dict[key] = value; } 
    } 

    public bool Contains(KeyValuePair<T1, T2> item) 
    { 
     return _dict.Contains(item); 
    } 

    public bool ContainsKey(T1 key) 
    { 
     return _dict.ContainsKey(key) && _dict[key].Count > 0; // This hides the smell 
    } 

    public int Count { get { return _dict.Count(kvp => kvp.Value.Count > 0); } } // This hides the smell 

    public void Add(T1 key, T2 value) 
    { 
     T2 currentValue; 
     if (_dict.TryGetValue(key, out currentValue) && currentValue.Count > 0) 
      throw new ArgumentException("A non empty element with the same key already exists in the SmellyDictionary"); 
     _dict[key] = value; 
    } 

    public void Add(KeyValuePair<T1, T2> item) 
    { 
     Add(item.Key, item.Value); 
    } 

    public bool Remove(T1 key) 
    { 
     return _dict.Remove(key); 
    } 

    public bool Remove(KeyValuePair<T1, T2> item) 
    { 
     return _dict.Remove(item); 
    } 

    public bool TryGetValue(T1 key, out T2 value) 
    { 
     return _dict.TryGetValue(key, out value); 
    } 

    public ICollection<T1> Keys { get { return _dict.Keys; } } 
    public ICollection<T2> Values { get { return _dict.Values; } } 
    public object SyncRoot { get { return ((ICollection)_dict).SyncRoot; } } 
    public bool IsSynchronized { get { return ((ICollection)_dict).IsSynchronized; } } 

    public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator() 
    { 
     return _dict.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    public void Clear() 
    { 
     _dict.Clear(); 
    } 

    public void CopyTo(Array array, int index) 
    { 
     _dict.CopyTo((KeyValuePair<T1, T2>[])array, index); 
    } 

    public void CopyTo(KeyValuePair<T1, T2>[] array, int arrayIndex) 
    { 
     _dict.CopyTo(array, arrayIndex); 
    } 

    public bool IsReadOnly { get { return _dict.IsReadOnly; } } 
} 
1

Voici une option légèrement plus sensible. Appelez simplement cette méthode pour ajouter une chaîne à votre dictionnaire.

private void AddCityToDictionary(Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary, BiomeType biome, LocationType location, string city) 
    { 
     Dictionary<LocationType, List<string>> locationDictionary; 
     if (!myDictionary.TryGetValue(biome, out locationDictionary)) 
      locationDictionary = myDictionary[biome] = new Dictionary<LocationType, List<string>>(); 
     List<string> cityList; 
     if (!locationDictionary.TryGetValue(location, out cityList)) 
      cityList = locationDictionary[location] = new List<string>(); 
     cityList.Add(city); 
    }