- ベストアンサー
C#のジェネリックで多次元マップを扱う方法
- C#でC++のテンプレートのような多次元マップを扱う方法について教えてください。
- Dictionaryを使用して多次元マップを表現することは可能ですが、異なるキーごとに新たなDictionaryを作成する必要があります。
- 他の方法としては、キーをペアにする方法もありますが、実装が煩雑になる可能性があります。スマートな方法や意見があれば教えてください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
ごめんなさい。急いでたので間違えました。 <T, X<U,V>>型は、キーが二つあるハッシュテーブルではありません。 >第1キーが異なれば毎回newする必要があります むしろこれで正解です。宣言はヒープにメモリを確保したに過ぎず、 nullしか入らないはずです。 Stackに確保するStruct型ならnewしなくても初期値が入るようになってますが。 構造上、a[][]はジャグあるいは方形配列で、また連想配列にするとすれば、2回の参照がありえます。{a->[]}->[] ですが、ジェネリック型は型をジェネリックにしてるに過ぎず、 参照先は1階層しかありません。 そっくりですが、オブジェクト指向てきにやってることが違うので、 まずはそれだけでの実装はできません。 そこで、ラッパークラスを作る必要があります。 class TowKeysDictionary<T,U>{ Dictionary<T, Dictionary<U,object>> dic1; // 適当に初期化しといて Dictionary<U,Object> innerDic; // 適当に初期化しといて public TowKeysCollection(){ ;} public object this[T key1, U key2]{ get{ // ここで実装 // key1 と key2で値を返してください。null注意。 } set{ // ここで実装 // key1とkey2で値を入れてください。 } } } これなら、 TowKeysDictionary<int, float> dic = new TowKeysDictionary<int,float>(); dic[1, 0.1] = aaaa; object b = dic[222, 333]; などが可能です。 なお、foreachで使いたいのなら、IDictionaryを継承してください。
その他の回答 (1)
- Xaval
- ベストアンサー率58% (61/105)
まずひとつ。 方形配列は使えませんか?flaot[,]a = new float[3,4]; また、キーが二つのディクショナリは、適当にクラスを作成してください。 public class AA<int,int>{ }
お礼
ご回答ありがとうございます。 >方形配列は使えませんか?flaot[,]a = new float[3,4]; 分かりにくくてすみません。キーを2つのintにしているのは例です。 2次元配列として使いたい場合は上記のような例で良いと思いますが map< string , map< string , string > > といった場合も使う方法があるということでしょうか? あと[10000][10000]の部分しか使わない場合 flaot[,]a = new float[10001,10001];と宣言するのは 無駄にメモリを食いつぶしてしまいますよね? >また、キーが二つのディクショナリは、適当にクラスを作成してください。 >public class AA<int,int>{ >} 上記ですがちょっとよくわかりません。 当方の理解不足で申し訳ありません。 とりあえず自分なりに解釈すると public class AA<T1,T2>{ T1 x; T2 y; public AA(T1 _x, T2 _y) { x = _x; y = _y; } public override bool Equals(object obj) { AA<T1, T2> right = (AA<T1, T2>)obj; return (right.x.Equals(x) && right.y.Equals(y)); } public override int GetHashCode() { return x.GetHashCode() + y.GetHashCode(); } } でAA<int , int> を使うということでしょうか? だとすると質問の public struct Pair{ int x; int y; Pair(int _x, int _y) { x = _x; y = _y; } } と同じような気がします。 もし再度お答え頂ければ幸いです。
お礼
丁寧にご回答頂きありがとうございます。 なるほどラップして使うという方法、とても参考になりました。 IDirctionary< T , Dictionary<U,Object> >の継承を http://msdn2.microsoft.com/ja-jp/library/system.collections.idictionary(VS.80).aspx を参考にしてみましたがちょっとめんどくさいですね。 enumを使うだけならIEnumerableのみでもいいかなと思いました。 とりあえず参考までにXavalさんを元に簡単に作ってみました。 class TowKeysDictionary<T, U> : IEnumerable<KeyValuePair< T , Dictionary<U, Object>>> { Dictionary<T, Dictionary<U, Object>> dictionary = new Dictionary<T, Dictionary<U, Object>>(); public TowKeysDictionary() { } public Object this[T key1, U key2] { get { return dictionary[key1][key2]; } set { if (!dictionary.ContainsKey(key1)) { dictionary[key1] = new Dictionary<U, Object>(); } dictionary[key1][key2] = value; } } public IEnumerator<KeyValuePair<T, Dictionary<U, Object>>> GetEnumerator() { foreach (KeyValuePair<T, Dictionary<U, Object>> obj in dictionary) { yield return obj; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable<Dictionary<U, Object>>)this).GetEnumerator(); } }