何をしたいユーティリティか:「マップ生成」
ここでの「マップ生成」は、配列から「キー → 値」の対応表(オブジェクトや Map)を作る処理のことです。
「id からユーザーを引けるようにしたい」「コードからラベルを引けるようにしたい」といったときに使います。
配列のままだと「毎回 find で探す」ことになりがちですが、
一度マップを作っておけば、map.get(id) のように一発で取り出せるようになります。
基本形:オブジェクトでマップを作る(キーは文字列前提)
シンプルな key → item のマップ
まずは一番よくある、「id から要素を引けるマップ」をオブジェクトで作るユーティリティです。
function toMapById(array, keyProp = "id") {
if (!Array.isArray(array)) {
return {};
}
const map = {};
for (const item of array) {
if (item && item[keyProp] != null) {
const key = String(item[keyProp]);
map[key] = item;
}
}
return map;
}
JavaScriptここでの重要ポイントをかみ砕きます。
配列でなければ空オブジェクトを返す(安全側)。keyProp(デフォルトは "id")でキーにするプロパティを指定できる。null / undefined なキーはスキップする(壊れたキーを入れない)。
キーは String(...) で文字列化してから使う(オブジェクトのキーは文字列だから)。
これで、「id → 要素」のマップが作れます。
動作例
const users = [
{ id: 1, name: "Taro" },
{ id: 2, name: "Hanako" },
];
const userMap = toMapById(users);
userMap["1"]; // { id: 1, name: "Taro" }
userMap["2"]; // { id: 2, name: "Hanako" }
JavaScript数値の id でも、内部では "1" のような文字列キーとして扱われます。
実務では「API から来る id は文字列」のことも多いので、どちらでも動くようにしておくと安心です。
汎用版:キーと値を関数で指定できる toMap
keySelector / valueSelector を受け取る
もう少し柔軟に、「キーも値も自分で決めたい」場合のユーティリティです。
function toMap(array, keySelector, valueSelector = (x) => x) {
if (!Array.isArray(array)) {
return {};
}
if (typeof keySelector !== "function") {
return {};
}
const map = {};
array.forEach((item, index) => {
const rawKey = keySelector(item, index);
if (rawKey == null) {
return;
}
const key = String(rawKey);
const value = valueSelector(item, index);
map[key] = value;
});
return map;
}
JavaScript重要ポイントはここです。
keySelector で「キーにする値」を決める。
valueSelector で「マップに入れる値」を決める(省略時は元の要素)。
キーが null / undefined のものはスキップする。
キーは文字列化してからオブジェクトに入れる。
これで、「id → item」「code → label」「id → name」など、いろいろなマップを作れます。
動作例1:id → ユーザー
const userMap = toMap(users, (u) => u.id);
// { "1": {…}, "2": {…} }
JavaScript動作例2:コード → ラベル
const statuses = [
{ code: "A", label: "有効" },
{ code: "D", label: "削除済み" },
];
const statusLabelMap = toMap(
statuses,
(s) => s.code,
(s) => s.label
);
// statusLabelMap["A"] === "有効"
// statusLabelMap["D"] === "削除済み"
JavaScript「コードからラベルを引く」という、業務で超よくあるパターンが一行で書けます。
Map オブジェクト版:キーにオブジェクトや数値をそのまま使いたいとき
なぜ Map を使うのか
オブジェクトのキーは文字列(とシンボル)に限られますが、Map なら「数値」「オブジェクト」「配列」などもそのままキーにできます。
「数値のままキーにしたい」「オブジェクトをキーにしたい」ような場面では、Map 版のユーティリティが便利です。
toKeyedMap
function toKeyedMap(array, keySelector, valueSelector = (x) => x) {
if (!Array.isArray(array) || typeof keySelector !== "function") {
return new Map();
}
const map = new Map();
array.forEach((item, index) => {
const key = keySelector(item, index);
if (key == null) {
return;
}
const value = valueSelector(item, index);
map.set(key, value);
});
return map;
}
JavaScriptここでは、キーを文字列化せず、そのまま map.set(key, value) しています。Map なので、map.get(key) で同じキーを渡せば値が取れます。
動作例:数値キーの Map
const userMap = toKeyedMap(users, (u) => u.id);
userMap.get(1); // { id: 1, name: "Taro" }
userMap.get(2); // { id: 2, name: "Hanako" }
JavaScriptオブジェクトキーを使うような高度なケースは、初心者のうちはあまり出てこないので、
まずは「数値キーをそのまま使える」くらいのイメージで大丈夫です。
なぜ「マップ生成」が業務で強いのか
探索コストが劇的に下がる
配列のまま「id で探す」と、毎回 find になります。
const user = users.find((u) => u.id === targetId);
JavaScriptこれは要素数が増えるほど遅くなります(1 件ずつ見ていくから)。
一方、マップにしておけば、
const user = userMap[targetId]; // オブジェクト版
// または
const user = userMap.get(targetId); // Map 版
JavaScriptで一発です。
「何度も同じキーで引く」処理があるなら、マップ生成はほぼ必須テクニックです。
コードの意図がはっきりする
toMapById や toMap を通すことで、「これは“id から引くためのマップ”なんだな」と一目で分かります。
配列のまま find を書いていると、
「これはたまたま一回だけ探しているのか」「実は何度も呼ばれていて重いのか」が見えづらいですが、
マップにしておけば「ここで索引用の構造を作っている」と明示できます。
手を動かして感覚をつかむ
ブラウザのコンソールなどで、次のように試してみてください。
function toMapById(array, keyProp = "id") {
if (!Array.isArray(array)) return {};
const map = {};
for (const item of array) {
if (item && item[keyProp] != null) {
const key = String(item[keyProp]);
map[key] = item;
}
}
return map;
}
function toMap(array, keySelector, valueSelector = (x) => x) {
if (!Array.isArray(array) || typeof keySelector !== "function") return {};
const map = {};
array.forEach((item, index) => {
const rawKey = keySelector(item, index);
if (rawKey == null) return;
const key = String(rawKey);
const value = valueSelector(item, index);
map[key] = value;
});
return map;
}
const users = [
{ id: 1, name: "Taro" },
{ id: 2, name: "Hanako" },
];
const userMap1 = toMapById(users);
const userMap2 = toMap(users, (u) => u.id, (u) => u.name);
JavaScriptuserMap1["1"] や userMap2["2"] を触ってみて、「配列からマップに変わると、どうアクセスしやすくなるか」を体感してみてください。
そのうえで、自分のプロジェクトに
export function toMapById(...) { ... }
export function toMap(...) { ... }
export function toKeyedMap(...) { ... }
JavaScriptのような関数を置き、「配列から“キーで引ける形”にしたくなったら、必ずこの“マップ生成ユーティリティ”を通す」と決めてみてください。
それだけで、find だらけのコードから、一段スケーラブルな設計に進めます。
