Map型したい(Map)

1const map = new Map();

Map型は、ECMAScript2015(ES6)で追加されたビルトイン型で、Object型と同じ、キーと値の組み合わせ(Key-Value Pair)を持つデータ構造です。 new Map()コンストラクターでMapを初期化できます。

Object型と異なり、プロパティの追加順が保証されています。 また、キーや値にオブジェクトとプリミティブ値を使用できたりします。 大量のデータを扱う場合には、Object型よりパフォーマンスがよいそうです。

1const map = new Map([
2  ["key1", "a1"],
3  ["key2", "b1"],
4  ["key3", "c1"],
5])

[key, value]ペアを要素にもつ2次元配列を与えて初期化できます。

値を追加したい(Map.set)

1const map = new Map();
2map.set("key1", "a1");
3map.set("key2", "b1");
4map.set("key3", "c1");

setメソッドで値(Key-Value Pair)を追加できます。

1map.get("key1");    // -> a1
2map.get("NO_KEY");  // -> undefined

getメソッドでキーを指定して、値を取得できます。 存在しないキーを指定した場合はundefinedになります。

1map.delete("key2");    // -> true
2map.delete("NO_KEY");  // -> false

deleteメソッドで指定したキーを削除できます。 返り値はBooleanになっているので、削除できたかどうかの判定に利用できます。

1// キーの確認
2if (map.has("key3")) {
3    // キーが存在するときの処理
4}

hasメソッドで、キーが存在するか確認できます。

1map.size;  // -> 3

sizeはプロパティ(メソッドではない)で、Mapオブジェクトの要素数を取得できます。

値を確認したい

1console.log(map);
2// -> Map(3) { 'key1' => 'a1', 'key2' => 'b1', 'key3' => 'c1' }
3
4Array.from(map);  // -> [[キー, 値]]
5Array.from(map.entries()); // -> [[キー, 値]]
6Array.from(map.keys());  // -> [キー]
7Array.from(map.values());  // -> [値]

console.logでそのまま出力するとMap(要素数) { ... }の形式で確認できます。 .keys、.values、.entriesでMapオブジェクトのプロパティを取得できます。 ただし、そのまま出力してもMap(...) {}という表示になるだけなので、 配列として中身を確認したい場合はArray.fromで変換すると見やすいです。

キー名を変更したい

1if (map.has("oldKey")) {
2    map.set("newKey", map.get("oldKey"));
3    map.delete("oldKey");
4}

キー名を直接変更するメソッドはありませんが、has、set、get、deleteを総動員させるとできます。 キーの順番が変更されるので注意が必要です。

キーの順番をソートしたい

1const sorted = [...sourceMap.entries()].sort((a, b) => {
2    // キーを文字列として比較
3    return a[0].localeCompare(b[0]);
4});
5const sortedMap = new Map(sorted);

entries()をスプレッド演算子で配列に変換し、sortで並び替えてから、 new Map()に渡すとキーの順番をソートし直せます。

ループしたい

1// for...ofループ
2for (const [key, value] of map) {
3    console.log(`${key}=${value}`);
4}

Mapはそれ自体が反復可能(iterable)なので、Objectと違いfor...ofにそのまま渡せます。

グループ化したい(Map.groupBy)

 1const people = [
 2    { name: "Alice", age: 20 },
 3    { name: "Bob", age: 30 },
 4    { name: "Carol", age: 20 },
 5];
 6
 7const grouped = Map.groupBy(people, (person) => person.age);
 8// -> Map(2) {
 9//      20 => [{ name: "Alice", age: 20 }, { name: "Carol", age: 20 }],
10//      30 => [{ name: "Bob", age: 30 }]
11//    }

Map.groupBy(反復可能なオブジェクト, 条件を定義した関数)で、 関数の戻り値ごとにグループ化されたMapオブジェクトを作れます。

配列にしたい

1const entries = Array.from(map.entries());
2const keys = Array.from(map.keys());
3const values = Array.from(map.values());

Array.fromで配列に変換できます。

オブジェクトにしたい

1const object = Object.fromEntries(map);
2console.log(JSON.stringify(object));

Object.fromEntriesでオブジェクトに変換できます。 Map自体が反復可能なので.entries()は省略できますが、 明示的に書きたい場合はObject.fromEntries(map.entries())としても同じ結果になります。

特定のキーを取得したい

1// 取得したいキー
2const filterKeys = new Set(["key1", "key2"]);
3
4// 中間処理
5const filtered = Array.from(map.entries()).filter(([key]) => filterKeys.has(key));
6// -> [["key1", "a1"], ["key2", "b1"]]
7
8const filteredMap = new Map(filtered);
9// -> Map(2) { "key1" => "a1", "key2" => "b1" }

Map.entriesで配列に変換し、filterメソッドを使うことで、 Mapオブジェクトから特定のキー(とその値)を抽出できます。

リファレンス