- PR -

hashtable内にhashtableを入れたときのキー指定(追加登録)

1
投稿者投稿内容
ぽよぽよ
会議室デビュー日: 2007/02/07
投稿数: 9
投稿日時: 2007-02-07 14:22
C#初心者です。宜しくお願いします。

ハッシュテーブル(hash2)の中にハッシュテーブル(hash1)を入れる処理を行っています。

ハッシュテーブル(hash2)に既に存在するキーの値にハッシュテーブル(hash1)を
追加登録したのですが、指定のしかたがわかりません。
下記コードの☆の箇所で行いたいのですが、下記コードでは上書きされてしまいます。
そもそも、実現できるのかどうかも含めてどなたかご教授願います。


[コード]

Hashtable Hash2 = new Hashtable();
string[] s3;

//af(Hashtable)に入っている値
//1 キー:"Dtl,0,1" 値:"A"
//2 キー:"Dtl,1,1" 値:"B"
//3 キー:"Dtl,0,2" 値:"C"

//Dtl 0 2
//↑ ↑ ↑
//形式 列 行

foreach (string key in af.Keys) {

string afval = (string)af[key];
s3 = key.Split(',');

Hashtable Hash1 = new Hashtable();
Hash1.Add(s3[2], afval);

if (Hash2.ContainsKey(s3[1]) == false) {
//キーがない場合
Hash2.Add(s3[1], Hash1);
} else {
//☆ キーが既に存在する場合
Hash2[s3[1]] = Hash1;
}
}
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-07 14:58
いまいち理解できていないのですが、上記コードを実行したときに、
Hash2[0]に格納されたHashTableに最後に追加された要素(キーが2で値が"C"のもの)しか
入っていないものと思われます。
そうではなくて、要素2つ(キーが1で値が"A"のものと、キーが2で値が"C"のもの)が
入るようにしたいという意味でしょうか?
ぽよぽよ
会議室デビュー日: 2007/02/07
投稿数: 9
投稿日時: 2007-02-07 15:07
返答ありがとうございます。
引用:

そうではなくて、要素2つ(キーが1で値が"A"のものと、キーが2で値が"C"のもの)が
入るようにしたいという意味でしょうか?



まったくその通りです。
VB6.0をやってたころはDictionaryObjectでできた気がするのですが...
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-07 15:27
foreachの1回目のループでは、Hash2にはキーが1で、
値は要素数1のHashTable(以下、HashTableAと呼ぶことにします)が追加されます。
ちなみにAの要素はキーが1、値がAのものになります。
3回目のループでは、Hash2.ContainsKey(1)はtrueを返すためelse句が処理されます。
なぜなら1回目のループで、キーが1の要素は既に追加されているからです。
ここまでは大丈夫ですよね?

で、問題の3回目のループなのですが…
Hash1という変数名でHashTableを生成していますが、
これはここで生成した新しいHashTableですから、HashTableAとは全くの別物です。
(以下、HashTableBと呼ぶことにします)
Hash2[1] = HashTableBと書いているわけですから、
もともと格納されていたHashTableAは「上書き」されてしまうのです。
ですから、3回目のループではHashTableを新たに生成するのではなく、
既にHash2[1]に格納されているHashTableAを取得して、
その要素を「追加」してやるようにすれば上手くいくはずです。
ぽよぽよ
会議室デビュー日: 2007/02/07
投稿数: 9
投稿日時: 2007-02-07 16:31
引用:

既にHash2[1]に格納されているHashTableAを取得して、
その要素を「追加」してやるようにすれば上手くいくはずです。



KIさん。ありがとうございました。
仰るとおり、Hash2[1]に格納されている要素を追加したらうまくいきました。
(下記 "◎追加")


Hashtable Hash2 = new Hashtable();
string[] s3;

//af(Hashtable)に入っている値
//1 キー:"Dtl,0,1" 値:"A"
//2 キー:"Dtl,1,1" 値:"B"
//3 キー:"Dtl,0,2" 値:"C"

//Dtl 0 2
//↑ ↑ ↑
//形式 列 行

foreach (string key in af.Keys) {

string afval = (string)af[key];
s3 = key.Split(',');

Hashtable Hash1 = new Hashtable();
Hash1.Add(s3[2], afval);

if (Hash2.ContainsKey(s3[1]) == false) {
//キーがない場合
Hash2.Add(s3[1], Hash1);
} else {

//◎追加--------------------------------
Hashtable hash3 = new Hashtable();
hash3 = (Hashtable) Hash2[s3[1]];

foreach (string Akey in hash3.Keys) {
string val = (string)hash3[Akey];
Hash1.Add(Akey, val);
}

Hash2[s3[1]] = Hash1;
//◎追加--------------------------------
}
}
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-07 17:05
うまくは行ったのかも知れませんが、コードにいくつか問題がありますので指摘しておきます。
上記コードだと、動作はするかも知れませんが無駄な処理が多いので、
レコードが増えるとパフォーマンスの低下が懸念されます。

引用:

Hashtable hash3 = new Hashtable();
hash3 = (Hashtable) Hash2[s3[1]];


上の行の「 = new Hashtable()」は不要です。
上の行で新しいHashTableを生成して、hash3という変数に格納していますが、
ここで生成したHashtableは全く使われることがありません。
何故だかわかりますか?

引用:

foreach (string Akey in hash3.Keys) {
string val = (string)hash3[Akey];
Hash1.Add(Akey, val);
}

Hash2[s3[1]] = Hash1;


Hash3からHash1にコピーして、それをまた設定しているようですが、
そんなことをせずとも、Hash3に直接追加すればいいのです。
それに伴い、新しいHashtableをnewするのは、
新しい要素を追加するときだけでよくなります。


一応、foreach部分の修正したコードを載せておきますが
「オブジェクトをnewするとはどういうことか?」ですとか「値型と参照型の違い」ですとか、
基礎をしっかりと勉強されたほうがよいと思います。

コード:

foreach (string key in af.Keys) { 

    string afval = (string)af[key]; 
    s3 = key.Split(','); 

    if (Hash2.ContainsKey(s3[1]) == false) { 

        Hashtable Hash1 = new Hashtable(); 
        Hash1.Add(s3[2], afval); 

        Hash2.Add(s3[1], Hash1); 

    } else { 

        Hashtable hash3; 
        hash3 = (Hashtable) Hash2[s3[1]]; 
        hash3.Add(s3[2], afval); 

    }
} 


#未確認なのでケアレスミスあったらすみません。
ぽよぽよ
会議室デビュー日: 2007/02/07
投稿数: 9
投稿日時: 2007-02-07 17:46
引用:

「オブジェクトをnewするとはどういうことか?」ですとか「値型と参照型の違い」ですとか、
基礎をしっかりと勉強されたほうがよいと思います。



上記、早速調べて見ました。
newすることで無駄に実体を作っていることに気づきました。
仰るとおり基礎をしっかりと勉強したいと思います。

KIさん、ご指摘どうもありがとうございました。

1

スキルアップ/キャリアアップ(JOB@IT)