1. ホーム
  2. JavaScript

【JavaScript】Map と Set の使い方|キーと値の管理・配列の重複排除を解説

Share

JavaScript で「キーと値のペアをまとめたい」「重複のないリストを作りたい」というとき、オブジェクトや配列でも書けますが、専用の MapSet を使うとずっとスッキリ書けます。この記事では、MapSet の基本的な使い方、オブジェクトや配列との違い、ループの回し方、そして配列との相互変換までを、コード例とともに解説します。連想配列のような処理や重複排除をきれいに書きたい初心者〜中級者の方が対象です。

Map と Set は何のためにあるのか

Map(マップ)は「キーと値のペア」を順番に保持するコレクションです。オブジェクト({})と似ていますが、キーに文字列以外(数値・オブジェクト・関数など)も使え、要素数を size で簡単に取れるといった利点があります。

Set(セット)は「重複しない値の集まり」です。同じ値を追加しても1つしか保持されないため、配列から重複を取り除く用途で特によく使われます。どちらも ES2015(ES6)で追加された、モダンな JavaScript の標準機能です。

Map の基本的な使い方

new Map() で空のマップを作り、set() で値を追加、get() で取り出します。キーの有無は has()、削除は delete() で行います。

map-basic.js
const stock = new Map();

stock.set("apple", 30);   // キー "apple" に値 30 を登録
stock.set("banana", 12);

console.log(stock.get("apple")); // 30
console.log(stock.has("banana")); // true
console.log(stock.size);          // 2(要素数)

stock.delete("banana");           // キーごと削除
console.log(stock.has("banana")); // false

初期値をまとめて渡したいときは、[キー, 値] の配列を並べた二次元配列をコンストラクタに渡します。

map-init.js
const colors = new Map([
  ["red", "#ff0000"],
  ["green", "#00ff00"],
  ["blue", "#0000ff"],
]);

console.log(colors.get("green")); // #00ff00
console.log(colors.size);         // 3

Map の主なメソッド・プロパティ

よく使うものを表にまとめます。set() はマップ自身を返すので、map.set(a).set(b) のようにつなげて書ける点も覚えておくと便利です。

メソッド/プロパティ説明
set(key, value)キーと値を登録する(既存キーなら上書き)
get(key)キーに対応する値を取り出す(無ければ undefined
has(key)キーが存在するかを truefalse で返す
delete(key)指定したキーの要素を削除する
clear()すべての要素を削除する
size要素数(プロパティなので () は不要)

Map とオブジェクトの違い

「キーと値ならオブジェクトでもいいのでは?」と思うかもしれません。多くの場面でオブジェクトで十分ですが、次のような違いがあるため、用途によって Map が向くことがあります。

観点Mapオブジェクト
キーの型何でも使える(数値・オブジェクト等)文字列とシンボルに限られる
要素数の取得size ですぐ取れるObject.keys().length が必要
順序追加した順序が保証される基本は追加順だが例外がある
繰り返しそのまま for...of で回せるObject.entries() 等が必要

キーが文字列で固定の「設定値のまとまり」ならオブジェクト、キーが動的に増減したり数値・オブジェクトをキーにしたいなら Map、と考えると選びやすいです。

Map をループで回す

Mapfor...of でそのまま繰り返せます。各要素は [キー, 値] の形なので、分割代入で受け取ると読みやすくなります。forEach() も使えますが、引数の順番が (値, キー) である点に注意してください。

map-loop.js
const stock = new Map([
  ["apple", 30],
  ["banana", 12],
]);

// for...of で [キー, 値] を分割代入
for (const [name, count] of stock) {
  console.log(`${name}: ${count}個`);
}
// apple: 30個
// banana: 12個

// キーだけ・値だけが欲しいとき
console.log([...stock.keys()]);   // ["apple", "banana"]
console.log([...stock.values()]); // [30, 12]

Set の基本的な使い方

Setadd() で値を追加し、has() で存在確認、delete() で削除します。同じ値を何度 add() しても、保持されるのは1つだけです。

set-basic.js
const tags = new Set();

tags.add("css");
tags.add("js");
tags.add("css"); // 既にあるので追加されない

console.log(tags.has("js")); // true
console.log(tags.size);      // 2("css" は1つだけ)

tags.delete("js");
console.log([...tags]);      // ["css"]

Set で配列の重複を取り除く

Set の最もよく使う用途が、配列の重複排除です。配列を new Set() に渡すと重複が自動で消え、スプレッド構文 [...set] で配列に戻せます。1行で書けるのが魅力です。

set-unique.js
const numbers = [1, 2, 2, 3, 3, 3, 4];

// Set に通してから配列に戻すと重複が消える
const unique = [...new Set(numbers)];

console.log(unique); // [1, 2, 3, 4]

同じ値かどうかは「厳密等価(===)」に近い比較で判定されます。そのため文字列の "1" と数値の 1 は別物として扱われ、両方残ります。重複排除の前に型をそろえておくと、意図しない残り方を防げます。

思った通りに重複が消えないとき

オブジェクトの配列は重複が消えない

Set はオブジェクトを「同じ中身か」ではなく「同じ参照か」で比較します。そのため {id: 1} が2つあっても、別々に作られたオブジェクトなら重複とは見なされず、両方残ります。オブジェクトの配列から重複を消したいときは、id など特定のキーを基準に Map でまとめ直すのが定番です。

dedupe-objects.js
const users = [
  { id: 1, name: "佐藤" },
  { id: 2, name: "鈴木" },
  { id: 1, name: "佐藤" }, // id が重複
];

// id をキーにした Map にまとめると、後勝ちで1件になる
const map = new Map(users.map((u) => [u.id, u]));
const unique = [...map.values()];

console.log(unique.length); // 2

size を length と書いてしまう

MapSet の要素数は size プロパティです。配列の感覚で .length と書くと undefined になります。要素数が欲しいときは size、と覚えておきましょう。

まとめ

MapSet は、キーと値の管理や重複排除をシンプルに書くための便利なコレクションです。要点を振り返ります。

  • Mapset()get()has() でキーと値を扱い、要素数は size
  • キーに文字列以外を使いたい・要素数や順序が重要なら Map が向く
  • Set は重複しない値の集まり。[...new Set(配列)] で重複排除できる
  • オブジェクトの配列は参照で比較されるため、Map でキーを基準にまとめる

まずは配列の重複排除で Set を、設定値や集計で Map を使ってみると、その手軽さを実感できるはずです。

参考ページ