連想配列
連想配列の操作についてまとめます。
Examples:
データ操作
import std : assertThrown; import core.exception : RangeError; // Keyの型が`K`, Valueの型が`V`の連想配列の型は`V[K]`と表されます。 int[string] data; // `[key]`で対応するValueにアクセスできます。 data["x"] = -3; data["y"] = +2; assert(data["x"] == -3); assert(data["y"] == +2); // 既に存在するKeyに対して代入した場合、Valueが更新されます。 data["x"] = -4; assert(data["x"] == -4); // 存在しないKeyに対応するValueを得ようとすると`RangeError`が発生します。 assertThrown!RangeError(data["z"]); // `.length`で挿入されているデータの数を取得できます。 assert(data.length == 2); // `in`であるKeyが挿入されているかどうかが判定できます。 assert("x" in data); assert("y" in data); assert("z" !in data); // `.remove`で指定したKeyに対応したデータを削除できます。 data.remove("x"); assert("x" !in data); assert("y" in data); assert("z" !in data); // `[key : value, ...]`でリテラルとしての連想配列を扱うことができます。 data = ["a": 100, "b": 200]; assert(data["a"] == 100); assert(data["b"] == 200); assert("x" !in data); // `in`は参照した値のポインタを返しているので、`if`と組み合わせるのが有効です。 if (auto p = "a" in data) { assert(*p == 100); } if (auto p = "c" in data) { assert(false); }
Examples:
プロパティ
import std : sort, equal, map, array; string[string] data = ["key0" : "value0", "key1" : "value1",]; // `.keys`でKey一覧を配列として取得できます。 // ただし順序は実装依存であり、挿入/宣言順とは限りません。 assert(data.keys.sort.equal(["key0", "key1"])); // `.values`でValue一覧を配列として取得できます。 assert(data.values.sort.equal(["value0", "value1"])); // `.byKeyValue()`でKeyとValueのペア一覧をForward Rangeとして取得できます。 assert(data.byKeyValue().map!(pair => pair.key ~ " : " ~ pair.value) .array.sort.equal(["key0 : value0", "key1 : value1"])); // `null`でない連想配列を代入するとshallow copyが発生しますが、`dup`を使うことでdeep copyができます。 string[string] data2 = data.dup; data["key2"] = "value2"; assert("key2" !in data2); // `.get(key, defval)`で、もし`key`が存在したら対応するValueを、なければ`defval`を取得できます。 assert(data.get("key0", "") == "value0"); assert(data.get("key", "") == ""); // `.require(key,value)`で、もし`key`が存在したら対応するValueを、なければ`key`と`value`のペアを追加した上で`value`を返します。 assert(data.require("key0", "newValue") == "value0"); assert(data.require("newKey", "newValue") == "newValue"); assert(data["newKey"] == "newValue"); // `.update(key,create,update)`で、もし`key`が存在したら`update`で上書きを、なければ`create`でValueを代入します。 data.update("key0", () => "value100", (ref string oldValue) => "new " ~ oldValue); assert(data["key0"] == "new value0"); data.update("key100", () => "value100", (ref string oldValue) => "new " ~ oldValue); assert(data["key100"] == "value100"); // `.clear()`で全要素を削除できます。 data.clear(); assert(data.length == 0);
Examples:
空連想配列とnull
string[int] data, data2; // 宣言時、連想配列は`null`になっています。 assert(data is null); // 連想配列間での代入操作は基本的にshallow copyとなりますが、代入元が`null`の時に限り参照値は同期されません。 data2 = data; // `data`は`null`なので、shallow copyは発生しない。 data[0] = "value"; assert(data2.length == 0); // `data2`は`data`と同期していない。 // 代入元が`null`でない場合はshallow copyとなります。 data2 = data; // `data`は`null`ではないので、shallow copyが発生。 data[0] = "newValue"; assert(data2[0] == "newValue"); // `data2`は`data`と同期している。 // 要素なしの連想配列と`null`は厳密には異なります。要素なしの配列の場合にはshallow copyが発生します。 data.clear(); // `.clear()`を用いて要素なしの連想配列を作成 assert(data.length == 0); data2 = data; // `data`は要素はないが`null`ではないため、shallow copyが発生。 data[0] = "newNewValue"; assert(data2[0] == "newNewValue");