Question

J'ai un dictionnaire, quelque chose comme

Dictionary<Foo,String> fooDict

Je parcoure tout le dictionnaire, par exemple

.
foreach (Foo foo in fooDict.Keys)
    MessageBox.show(fooDict[foo]);

Cela fait que dans l'ordre dans lequel les foos ont été ajoutés au dictionnaire, le premier élément ajouté est le premier foo renvoyé.

Comment puis-je changer la cardinalité pour que, par exemple, le troisième toto ajouté soit le deuxième toto renvoyé? En d'autres termes, je souhaite modifier son "index".

Était-ce utile?

La solution

Si vous lisez la documentation sur MSDN, vous verrez ceci:

"L’ordre dans lequel les articles sont renvoyés n’est pas défini."

Vous ne pouvez pas garantir l'ordre car un dictionnaire n'est pas une liste ni un tableau. C’est censé rechercher une valeur par la clé, et toute possibilité d’itérer des valeurs n’est qu’une commodité, mais l’ordre n’est pas un comportement sur lequel vous devriez compter.

Autres conseils

Vous pouvez être intéressé par le OrderedDicationary de la classe < code> System.Collections.Specialized , espace de noms.

Si vous regardez les commentaires tout en bas, une personne de MSFT a posté cette note intéressante:

  

Ce type est en réalité mal nommé; ce n'est pas un dictionnaire "ordonné" en tant que tel, mais plutôt un dictionnaire "indexé". Bien qu’aujourd’hui, il n’existe pas de version générique équivalente de ce type, mais si nous en ajoutons une à l’avenir, il est probable que nous appellerons le type 'IndexedDictionary'.

Je pense qu'il serait trivial de dériver de cette classe et de créer une version générique de OrderedDictionary.

Je ne suis pas complètement au fait du domaine pour répondre correctement à la question, mais j’ai le sentiment que le dictionnaire trie les valeurs en fonction de la clé, afin de: effectuer une recherche rapide par clé. Cela suggérerait que le dictionnaire est trié par valeurs de clé en fonction de la comparaison de clé. Toutefois, en ce qui concerne les méthodes objet , je suppose qu'elles utilisent des codes de hachage pour comparer différents objets, étant donné que le type utilisé pour les clés n'est pas obligatoire. Ceci n'est qu'une supposition. Quelqu'un de plus averti devrait donner plus de détails.

Pourquoi souhaitez-vous manipuler le " index " d'un dictionnaire quand son but est d'indexer avec des types arbitraires?

Je ne sais pas si quelqu'un trouvera cela utile, mais voici ce que j'ai fini par comprendre. Cela semble fonctionner (je veux dire par là que cela ne jette aucune exception), mais je suis encore loin de pouvoir tester que cela fonctionne comme je l'espère. J'ai déjà fait la même chose auparavant.

        public void sortSections()
    {
        //OMG THIS IS UGLY!!!
        KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray();
        IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality);

        foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted)
        {
            TextSection sec = kvp.Value;
            ListViewItem key = kvp.Key;

            textSecs.Remove(key);
            textSecs.Add(key, sec);
        }
    }

La réponse courte est qu'il ne devrait pas y avoir de solution, car un dictionnaire "représente une collection de clés et de valeurs". ce qui n'implique aucune sorte d'ordre. Tout piratage que vous pourriez trouver est en dehors de la définition de la classe et est susceptible de changer.

Vous devriez probablement d'abord vous demander si un dictionnaire est vraiment nécessaire dans cette situation, ou si vous pouvez vous en sortir en utilisant une liste de KeyValuePairs.

Sinon, quelque chose comme ceci pourrait être utile:

public class IndexableDictionary<T1, T2> : Dictionary<T1, T2>
{
    private SortedDictionary<int, T1> _sortedKeys;

    public IndexableDictionary()
    {
        _sortedKeys = new SortedDictionary<int, T1>();
    }
    public new void Add(T1 key, T2 value)
    {
        _sortedKeys.Add(_sortedKeys.Count + 1, key);
        base.Add(key, value);
    }

    private IEnumerable<KeyValuePair<T1, T2>> Enumerable()
    {
        foreach (T1 key in _sortedKeys.Values)
        {
            yield return new KeyValuePair<T1, T2>(key, this[key]);
        }
    }

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

    public KeyValuePair<T1, T2> this[int index]
    {
        get
        {
            return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]);
        }
        set
        {
            _sortedKeys[index] = value.Key;
            base[value.Key] = value.Value;
        }

    }


}

Le code client a l'apparence suivante:

    static void Main(string[] args)
    {
        IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>();

        fooDict.Add("One", "One");
        fooDict.Add("Two", "Two");
        fooDict.Add("Three", "Three");

        // Print One, Two, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);



        KeyValuePair<string, string> temp = fooDict[1];
        fooDict[1] = fooDict[2];
        fooDict[2] = temp;


        // Print Two, One, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);

        Console.ReadLine();
    }

UPDATE: Pour une raison quelconque, cela ne me permet pas de commenter ma propre réponse.

Quoi qu’il en soit, IndexableDictionary est différent de OrderedDictionary en cela

  1. "Les éléments d'un OrderedDictionary ne sont en aucun cas triés." Donc, foreach ne ferait pas attention aux indices numériques
  2. Il est fortement typé afin que vous n'ayez pas à perdre du temps à jeter des éléments hors de la structure DictionaryEntry
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top