Domanda

Ho un dizionario, qualcosa del genere

Dictionary<Foo,String> fooDict

Scorro tutto nel dizionario, ad esempio

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

Lo fa nell'ordine in cui i foo sono stati aggiunti al dizionario, quindi il primo elemento aggiunto è il primo foo restituito.

Come posso modificare la cardinalità in modo che, ad esempio, il terzo pippo aggiunto sia il secondo pippo restituito? In altre parole, voglio cambiare il suo "indice". & Quot;

È stato utile?

Soluzione

Se leggi la documentazione su MSDN vedrai questo:

" L'ordine in cui vengono restituiti gli articoli non è definito. "

Non puoi garantire l'ordine, perché un Dizionario non è un elenco o un array. Ha lo scopo di cercare un valore con la chiave e qualsiasi capacità di iterare i valori è solo una comodità, ma l'ordine non è un comportamento da cui dovresti dipendere.

Altri suggerimenti

Potresti essere interessato a Classe OrderedDicationary inclusa nella < code> System.Collections.Specialized spazio dei nomi.

Se guardi i commenti in fondo, qualcuno di MSFT ha pubblicato questa nota interessante:

  

Questo tipo è in realtà errato; non è un dizionario "ordinato" in quanto tale, ma piuttosto un dizionario "indicizzato". Anche se oggi non esiste una versione generica equivalente di questo tipo, se ne aggiungiamo una in futuro è probabile che ne nomineremo un tipo come "IndexedDictionary".

Penso che sarebbe banale derivare da questa classe e creare una versione generica di OrderedDictionary.

Non sono non completamente istruito nel dominio per rispondere correttamente alla domanda, ma ho la sensazione che il dizionario ordina i valori in base alla chiave, al fine di eseguire una ricerca rapida dei tasti. Ciò suggerirebbe che il dizionario sia ordinato in base ai valori delle chiavi in ??base al confronto delle chiavi. Tuttavia, osservando i metodi oggetto , suppongo che stiano usando codici hash per confrontare oggetti diversi considerando che non vi è alcun requisito sul tipo utilizzato per le chiavi. Questa è solo una supposizione. Qualcuno più consapevole dovrebbe compilare con maggiori dettagli.

Perché sei interessato a manipolare l'indice " di un dizionario quando il suo scopo è indicizzare con tipi arbitrari?

Non so se qualcuno lo troverà utile, ma ecco cosa ho scoperto. Sembra funzionare (con questo intendo dire che non genera alcuna eccezione), ma sono ancora molto lontana dalla possibilità di provare che funziona come spero. Tuttavia, ho già fatto una cosa simile.

        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 risposta breve è che non dovrebbe esserci un modo poiché un Dizionario " Rappresenta una raccolta di chiavi e valori. " che non implica alcun tipo di ordinazione. Qualsiasi hack che potresti trovare è al di fuori della definizione della classe e potrebbe essere soggetto a modifiche.

Probabilmente dovresti prima chiederti se un Dizionario è veramente richiesto in questa situazione o se puoi cavartela usando un Elenco di KeyValuePairs.

Altrimenti, potrebbe essere utile qualcosa di simile:

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;
        }

    }


}

Con il codice client simile a questo:

    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();
    }

AGGIORNAMENTO: per qualche motivo non mi consente di commentare la mia risposta.

Comunque, IndexableDictionary è diverso da OrderedDictionary in quello

  1. " Gli elementi di un OrderedDictionary non sono ordinati in alcun modo. " Quindi i foreach non presterebbero attenzione agli indici numerici
  2. È fortemente tipizzato, quindi non devi preoccuparti di lanciare oggetti dalle strutture DictionaryEntry
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top