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オブジェクトから特定のキー(とその値)を抽出できます。