[C#] C#での多次元キーによるハッシュテーブル


Answers

何らかの種類のタプル構造を持つ正規の辞書をキーとして使うのはどうですか?

public class TwoKeyDictionary<K1,K2,V>
{
    private readonly Dictionary<Pair<K1,K2>, V> _dict;

    public V this[K1 k1, K2 k2]
    {
        get { return _dict[new Pair(k1,k2)]; }
    }

    private struct Pair
    {
        public K1 First;
        public K2 Second;

        public override Int32 GetHashCode()
        {
            return First.GetHashCode() ^ Second.GetHashCode();
        }

        // ... Equals, ctor, etc...
    }
}
Question

私は基本的には、C#で2次元の型付きキーを使用してハッシュテーブル値にアクセスする方法を探しています。

最終的に私はこのようなことをすることができるだろう

HashTable[1][false] = 5;
int a = HashTable[1][false];
//a = 5

これは私が試みてきたことです...働いていません

Hashtable test = new Hashtable();
test.Add(new Dictionary<int, bool>() { { 1, true } }, 555);
Dictionary<int, bool> temp = new Dictionary<int, bool>() {{1, true}};
string testz = test[temp].ToString(); 



あなたは正しくgethashcodeを実装している二十八のためのキークラスが必要です。 そして、あなたはそれを友好的な方法でアクセスできるように二柱を拡張することができます。

キーペアクラス

public class KeyPair<Tkey1, Tkey2>
{
    public KeyPair(Tkey1 key1, Tkey2 key2)
    {
        Key1 = key1;
        Key2 = key2;
    }

    public Tkey1 Key1 { get; set; }
    public Tkey2 Key2 { get; set; }

    public override int GetHashCode()
    {
        return Key1.GetHashCode() ^ Key2.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        KeyPair<Tkey1, Tkey2> o = obj as KeyPair<Tkey1, Tkey2>;
        if (o == null)
            return false;
        else
            return Key1.Equals(o.Key1) && Key2.Equals(o.Key2);
    }
}

拡張Dictonary <>

public class KeyPairDictonary<Tkey1, Tkey2, Tvalue> 
    : Dictionary<KeyPair<Tkey1, Tkey2>, Tvalue>
{
    public Tvalue this[Tkey1 key1, Tkey2 key2]
    {
        get
        {
            return this[new KeyPair<Tkey1, Tkey2>(key1, key2)];
        }
        set
        {
            this[new KeyPair<Tkey1, Tkey2>(key1, key2)] = value;
        }
    }
}

あなたはこれをこのように使用します

        KeyPairDictonary<int, bool, string> dict = 
            new KeyPairDictonary<int, bool, string>();
        dict[1, false] = "test";
        string test = dict[1, false];



2次元キーを別のtypeラップし、そのタイプをキーとして使用します。 GetHashCode()Equals()メソッドをオーバーライドすることも検討してください。 HashTable代わりにDictionary<>を使用することをお勧めします。




素早く汚れた方法は、2つの情報から複合キーを作成することです。

IDictionary<string, int> values = new Dictionary<string, int>();
int i = ...;
bool b = ...;
string key = string.Concat(i, '\0', b);
values[key] = 555;

これを少しうまくカプセル化するには、辞書をラップすることができます:

public class MyDict
{
    private readonly IDictionary<string, int> values = new Dictionary<string, int>();

    public int this[int i, bool b]
    {
        get
        {
            string key = BuildKey(i, b);
            return values[key];
        }

        set
        {
            string key = BuildKey(i, b);
            values[key] = value;
        }
    }

    private static string BuildKey(int i, bool b)
    {
        return string.Concat(i, '\0', b);
    }
}

これをより堅牢にするには、コンポジットキーをタイプ(例えば、2つのフィールドを含むクラス)としてカプセル化し、Equals()メソッドとGetHashCode()メソッドを正しくオーバーライドするようにします。




つまり、あなたのメインディクショナリはDictionary<int, Dictionary<bool, my_return_type>>型のハッシュテーブルを「ダブルネスト」することができます。

これにより、最初のコードスニペットで二重括弧表記を使用できるという目標が達成されます。

もちろん、管理面は少し面倒です。 エントリを追加するたびに、メイン辞書にプライマリキーの辞書が含まれているかどうかをテストし、そうでなければ新しい辞書を追加してから、セカンダリのキーと値を内部ディクショナリに追加する必要があります。




boolとintの各プロパティを公開する小さなカスタムクラスを作成し、そのGetHashCodeメソッドとEqualsメソッドをオーバーライドし、これをキーとして使用することをお勧めします。




私はこれがあなたが探しているものに近いかもしれないと思う...

var data = new Dictionary<int, Dictionary<bool, int>>();