web-dev-qa-db-ja.com

辞書で最大のキーを取得する

私はintであるキーを持つ辞書を持っています。最大の鍵を取得したいのですが。私はキーを追跡していないので、キーは連続している可能性があります(たとえば、1,2,3,4,5,6)が、スキップする可能性があります(1,3,4,5)。

バイナリ検索を使用するだけですか、それとも方法はありますか?私が見る限り、そのような単純なタスクの二分探索に勝るものはほとんどありません-多分あなたはそれを半分にすることができます。

23
s5s

LINQを使用できる場合は、次のことができるはずです。

myDictionary.Keys.Max();
40
Ry-

キーは特定の順序で保存されないため、バイナリ検索が最速ですが、通常の辞書に対しては機能しません。通常の辞書を使用している場合は、Linq Max()を使用した@Minitechの回答が最も簡単です。

これが何度も実行する必要のある操作である場合は、キーに基づいてエントリを並べ替える_SortedDictionary<TKey, TValue>_に移動することを検討してください。

_var dict = new SortedDictionary<int, int> {{3, 0}, {12, 0}, {32, 0}, 
                                           {2, 0}, {16, 0}, {20, 0}};
Console.WriteLine(dict.Keys.Last()); //prints 32
_

編集:これは通常の辞書よりも遅くなる可能性があります。それを言って良かったと思います。これは、辞書のエントリが異なる方法で保存されるためです(赤/黒木とハッシュバケット/ハッシュテーブル)

isSortedDictionaryが通常のDictionaryよりも速くなるポイント。ただし、これはおそらく約100万アイテムになると思われますが、それは単なる推測です。その数のアイテムで約10倍高速であることがわかります(ただし、とにかく100分の1秒について話しているので、本当には重要ですか?) 。これは、100000アイテムのx64リリースとほぼ同じです。辞書に項目を追加するための余分なオーバーヘッドがあることを考えると、おそらくそれだけの価値はありません。また、比較対象をオーバーライドして逆の順序で並べ替えることで少し「だまされた」ので、実際には最後ではなくdict.Keys.First()を実行して最大のアイテムを取得しています。

SortedDictionaryは、すべてのKeyValueペアを順番に繰り返す必要がある場合に役立ちます。 @SimonMourierの答えがおそらく最高だと思います。最小限のオーバーヘッドで最速であることを保証します。

9

パフォーマンスが本当に問題になる場合は、既存のクラスの上に新しいクラスを作成し、次のような標準インターフェイスを実装します。

    public class RememberMaxDictionary<K, V> : IDictionary<K, V> where K: IComparable<K>
    {
        private Dictionary<K, V> _inner;

        public RememberMaxDictionary()
        {
            _inner = new Dictionary<K, V>();
        }

        public K MaxKey { get; private set; }

        public void Add(K key, V value)
        {
            _inner.Add(key, value);

            if (key.CompareTo(MaxKey) > 0) // test null if needed
            {
                MaxKey = key;
            }
        }

    ... TODO implement the rest...
2
Simon Mourier