GLibのハッシュテーブルをVala言語で用いる(後半)
「GLibのハッシュテーブルをVala言語で用いる(前半)」の続き。見出し「データの出し入れ」の中における続きとなる。
データの取り出し
ハッシュテーブルオブジェクトからキーを指定してデータを取り出すにはハッシュテーブルオブジェクトのメンバ関数lookup()にキーのデータを入れる。
全てのデータを取り出したい場合は
- HashTableIter構造体を用いた方法
- ハッシュテーブルオブジェクトのfor_each()を用いた方法
- ハッシュテーブルオブジェクトのget_keys()でキーの一覧を得る方法
の3つの方法がある。
最初の方法はテーブル内のキーと値の型を指定したものを用意した上でnext()をtrueを返す間繰り返し呼び出し続けてキーと値を取り出していく。下はキーにstring,値にintの型を用いるハッシュテーブルに対するHashTableIterの例。
[キーの型] key; [値の型] val; GLib.HashTableIter<string,int> iter = GLib.HashTableIter<string,int> ([ハッシュテーブルオブジェクト]); while (iter.next (out key, out val)) { ... }
2番目の方法は2つの引数(キーと値)を受け取る関数を用意するもので引数は両方void *型なので、それぞれを用いる際には型変換する必要がある。
[ハッシュテーブルオブジェクト].for_each ((key, val) =>
{
// key,valは型変換して用いる
});
3番目の方法はキーの一覧を得た上で、それぞれのキーに対する値をlookup()で取り出す。get_keys()の結果をforeach構文で処理すると書きやすい。型変換も不要。
foreach ([キーの型(「var」でも可)] key in [ハッシュテーブルオブジェクト].get_keys ()) { // 「[ハッシュテーブルオブジェクト].lookup (key)」でそれぞれのキーに対応する値を得る }
例1
内容は簡単なデータの出し入れで、全てのデータの取り出しもしている。
[任意]ファイル名: hashtabletest.vala
/* * ハッシュテーブルのテスト * * valac --pkg posix hashtabletest.vala -o hashtabletest */ using Posix; namespace HashTableTest { int main (string[] args) { string key; int val; // HashTableは「キー」とそれに対応した「値」をペアにして格納できるオブジェクト // キーと値の型はそれぞれ決めることができ // オブジェクトの型の中に「<[キーの型],[値の型]>」として記述する // 今回はキーを文字列,値を整数とした // コンストラクタ引数はキーの型に応じたハッシュ生成関数と // 比較関数(内容が一致したときにtrue,一致しないときにfalseを返すように記述されたもの)を指定 GLib.HashTable<string,int> fruits = new GLib.HashTable<string,int> (GLib.str_hash, GLib.str_equal); /* // 比較の関数を自前で記述する場合は一致したときにtrue,一致しない場合にfalseを返すようにする GLib.HashTable<string,int> fruits = new GLib.HashTable<string,int> (GLib.str_hash, (a, b) => { // 引数はvoid *型なので文字列としての比較のために型変換をする return ((string) a == (string) b); }); */ // HashTableIterはHashTableの中の項目を指し示して項目を移動できる構造体 GLib.HashTableIter<string,int> iter; // insert()やreplace()はキーと値のペアを追加する // キーが衝突した場合は新しいもので置き換えられる fruits.insert ("apple", 100); fruits.insert ("orange", 60); fruits.insert ("cherry", 40000); fruits.replace ("cherry", 40); // 40000というデータはここでなくなる // fruits.insert ("cherry", 40); // この例ではreplace()と挙動は同じ // キー指定による個別の取り出し print ("lookup: cherry=%d\n", fruits.lookup ("cherry")); // HashTableIterによる取り出し iter = GLib.HashTableIter<string,int> (fruits); while (iter.next (out key, out val)) { print ("iter: %s=%d\n", key, val); } // for_each()による取り出し // 引数はvoid *型なので型変換する fruits.for_each ((key, val) => { print ("for_each: %s=%d\n", (string) key, (int) val); }); // キーの一覧を取得してそのそれぞれの値を取り出す方法 // 最も書きやすい foreach (string key in fruits.get_keys ()) { print ("get_keys/foreach: %s=%d\n", key, fruits.lookup (key)); } return EXIT_SUCCESS; } }
下は実行例。
lookup: cherry=40 iter: apple=100 iter: cherry=40 iter: orange=60 for_each: apple=100 for_each: cherry=40 for_each: orange=60 get_keys/foreach: orange=60 get_keys/foreach: cherry=40 get_keys/foreach: apple=100
例2
例1をもとに、キーや値の破棄をする際に呼ばれる関数を用意したもの。
[任意]ファイル名: hashtabletest2.vala
/* * ハッシュテーブルのテスト2 * キーと値の破棄を行う関数を用意してそれを用いる形の例 * * valac --pkg posix hashtabletest2.vala -o hashtabletest2 */ using Posix; namespace HashTableTest { int main (string[] args) { string key; int val; GLib.HashTable<string,int> fruits = new GLib.HashTable<string,int>.full (GLib.str_hash, GLib.str_equal, (data) => { debug ("key_destroy_func: %s", (string) data); }, (data) => { debug ("value_destroy_func: %d", (int) data); }); GLib.HashTableIter<string,int> iter; fruits.insert ("apple", 100); fruits.insert ("orange", 60); fruits.insert ("cherry", 40000); fruits.replace ("cherry", 40); // fruits.insert ("cherry", 40); // この例ではreplace()と挙動は同じ print ("lookup: cherry=%d\n", fruits.lookup ("cherry")); iter = GLib.HashTableIter<string,int> (fruits); while (iter.next (out key, out val)) { print ("iter: %s=%d\n", key, val); } fruits.for_each ((key, val) => { print ("for_each: %s=%d\n", (string) key, (int) val); }); foreach (string key in fruits.get_keys ()) { print ("get_keys/foreach: %s=%d\n", key, fruits.lookup (key)); } print ("-- end of main() --\n"); return EXIT_SUCCESS; } }
下は実行例。最初の「DEBUG」の出力は項目「cherry」が更新されたことによる解放処理のもので、「-- end of main() --」の後ろの解放処理はハッシュテーブルのオブジェクト変数の寿命によるもの。
** (process:[プロセスID]): DEBUG: hashtabletest2.vala:19: key_destroy_func: cherry ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:22: value_destroy_func: 40000 lookup: cherry=40 iter: apple=100 iter: cherry=40 iter: orange=60 for_each: apple=100 for_each: cherry=40 for_each: orange=60 get_keys/foreach: orange=60 get_keys/foreach: cherry=40 get_keys/foreach: apple=100 -- end of main() -- ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:19: key_destroy_func: apple ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:22: value_destroy_func: 100 ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:19: key_destroy_func: cherry ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:22: value_destroy_func: 40 ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:19: key_destroy_func: orange ** (process:[プロセスID]): DEBUG: hashtabletest2.vala:22: value_destroy_func: 60
関連記事:
参考URL: