4

私は辞書を持っています

Dictionary<Foo,String> fooDict

私は辞書のすべてをステップスルーします、例えば

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

これは、fooが辞書に追加された順序で行われるため、最初に追加された項目が最初に返されるfooです。

たとえば、追加された3番目のfooが2番目に返されるfooになるように、カーディナリティを変更するにはどうすればよいですか?つまり、「インデックス」を変更したいのです。

4

5 に答える 5

8

MSDN のドキュメントを読むと、次のように表示されます。

「アイテムが返される順序は未定義です。」

Dictionary はリストでも配列でもないため、順序を保証することはできません。キーで値を検索することを意図しており、値を反復する機能は便利ですが、順序は依存すべき動作ではありません。

于 2008-09-24T23:45:24.697 に答える
5

名前空間に含まれるOrderedDicationaryクラスに興味があるかもしれません。System.Collections.Specialized

一番下のコメントを見ると、MSFT の誰かが次の興味深いメモを投稿しています。

この型は実際には間違った名前です。それ自体は「順序付けられた」辞書ではなく、むしろ「索引付けされた」辞書です。現在、この型に相当するジェネリック バージョンはありませんが、将来追加する場合は、「IndexedDictionary」型などの名前を付ける可能性があります。

このクラスから派生させて、OrderedDictionary の汎用バージョンを作成するのは簡単だと思います。

于 2008-09-25T01:08:08.103 に答える
0

私はこの分野で質問に適切に答えるための十分な教育を受けていませんが、辞書はキーに従って値をソートして、キーをすばやく検索できるようになっていると感じています。これは、辞書がキー比較に従ってキー値でソートされていることを示しています。ただし、オブジェクトメソッドを見ると、キーに使用されるタイプに要件がないことを考慮して、ハッシュコードを使用してさまざまなオブジェクトを比較していると思います。これは単なる推測です。より知識のある人は、より詳細に記入する必要があります。

辞書の目的が任意のタイプで索引付けすることであるのに、なぜ辞書の「索引」を操作することに興味があるのですか?

于 2008-09-24T23:42:06.017 に答える
0

誰かがこれを役に立つと思うかどうかはわかりませんが、これが私が最終的に理解したものです. 動作しているように見えます (つまり、例外がスローされないということです) が、期待どおりに動作することをテストできるようになるまでにはまだ時間がかかります。とはいえ、以前にも似たようなことをしたことがあります。

        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);
        }
    }
于 2008-09-25T00:34:34.753 に答える
0

手短に言えば、ディクショナリは「キーと値のコレクションを表す」ので、仕方がないということです。これは、いかなる順序付けも意味しません。あなたが見つけたハックはクラスの定義の外にあり、変更される可能性があります。

おそらく、この状況で Dictionary が本当に必要なのか、または KeyValuePairs のリストを使用して問題を解決できるのかをまず自問する必要があります。

それ以外の場合は、次のようなものが役立つ場合があります。

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

    }


}

クライアントコードは次のようになります。

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

更新:何らかの理由で、自分の回答についてコメントすることはできません。

とにかく、 IndexableDictionary は OrderedDictionary とは異なります。

  1. 「OrderedDictionary の要素は、どのような方法でも並べ替えられません。」したがって、foreach は数値インデックスに注意を払いません。
  2. 強く型付けされているため、DictionaryEntry 構造体から何かをキャストする必要はありません。
于 2008-09-25T00:40:34.143 に答える