はじめに
Mapオブジェクトを使ったことない人が、これ使えるかもと思える記事です。
詳細には説明しません。
グループ分けだけを見たい人はこちら
Mapオブジェクト
連想配列を管理するオブジェクトです。
下記のように使います。これ便利だろうか?よくわからん。
const team = new Map([
['name', 'Falcon'],
['member', ['Han', 'Chewie', 'Luke']],
]);
console.log(team);
// Map(2) { 'name' => 'Falcon', 'member' => [ 'Han', 'Chewie', 'Luke' ] }
// キーを指定して取得
console.log(team.get('name')); // "Falcon"
// キーを指定して追加
team.get('member').push('Leia');
console.log(team.get('member')); // ['Han', 'Chewie', 'Luke', 'Leia']
// サイズの取得
console.log(team.size); // 2
// 新規のキーとバリューの組み合わせ(エントリー)を追加
team.has('droid') || team.set('droid', ["C-3PO", "R2-D2"]);
console.log(team.get('droid')); // ['C-3PO', 'R2-D2']
console.log(team);
// Map(3) {
// 'name' => 'Falcon',
// 'member' => [ 'Han', 'Chewie', 'Luke', 'Leia' ],
// 'droid' => [ 'C-3PO', 'R2-D2' ]
// }
オブジェクトリテラルでもやってみる
ほぼ同じことができます。
この場合はサイズが取れません。
const team = {
name: "Falcon",
member: ['Han', 'Chewie', 'Luke'] ,
};
console.log(team['name']); // Falcon
team.member.push('Leia');
console.log(team.member); // [ 'Han', 'Chewie', 'Luke', 'Leia' ]
if (!team.hasOwnProperty('droid')) {
team.droid = ["C-3PO", "R2-D2 "];
}
console.log(team.droid); // [ 'C-3PO', 'R2-D2 ' ]
console.log(team);
// {
// name: 'Falcon',
// member: [ 'Han', 'Chewie', 'Luke', 'Leia' ],
// droid: [ 'C-3PO', 'R2-D2 ' ]
// }
Mapオブジェクトのキーについて
任意の型をキーにすることができ、Nanやundefindも用いることができる。
Mapオブジェクトを使ってグループ分け
次のようなオブジェクトの配列があったとします。
FalconのメンバーとそれぞれがcombatActionをもっています。
combatActionは戦闘時の動作をファンクションとして定義したプロパティです。
const Falcon = [
{ name: "Han", combatAction: pilot},
{ name: "Chewie", combatAction: support},
{ name: "Luke", combatAction: fight},
{ name: "Leia", combatAction: fight},
{ name: "R2-D2", combatAction: support},
{ name: "C-3PO", combatAction: quiet},
]
function pilot() {
console.log('pilot');
}
function fight() {
console.log('fight');
}
function support() {
console.log('support');
}
function quiet() {
console.log('');
}
combatActionが同じメンバーでグループを作るとします。
こんな感じにメンバーが分かれてくれると嬉しいです。
// 期待する結果
[
[ { name: 'Han', combatAction: [Function: pilot] } ],
[
{ name: 'Chewie', combatAction: [Function: support] },
{ name: 'R2-D2', combatAction: [Function: support] }
],
[
{ name: 'Luke', combatAction: [Function: fight] },
{ name: 'Leia', combatAction: [Function: fight] }
],
[ { name: 'C-3PO', combatAction: [Function: quiet] } ]
]
こういうときにMapオブジェクトを使うと便利です。
const Falcon = [
{ name: "Han", combatAction: pilot},
{ name: "Chewie", combatAction: support},
{ name: "Luke", combatAction: fight},
{ name: "Leia", combatAction: fight},
{ name: "R2-D2", combatAction: support},
{ name: "C-3PO", combatAction: quiet},
]
function pilot() {
console.log('pilot');
}
function fight() {
console.log('fight');
}
function support() {
console.log('support');
}
function quiet() {
console.log('');
}
const group = new Map();
Falcon.forEach(member => {
const combatAction = member.combatAction
// ファンクションをキーにして連想配列を作成する
if (group.has(combatAction)) {
group.get(combatAction).push(member);
} else {
group.set(combatAction, [member]);
}
});
console.log(group);
// Map(4) {
// [Function: pilot] => [ { name: 'Han', combatAction: [Function: pilot] } ],
// [Function: support] => [
// { name: 'Chewie', combatAction: [Function: support] },
// { name: 'R2-D2', combatAction: [Function: support] }
// ],
// [Function: fight] => [
// { name: 'Luke', combatAction: [Function: fight] },
// { name: 'Leia', combatAction: [Function: fight] }
// ],
// [Function: quiet] => [ { name: 'C-3PO', combatAction: [Function: quiet] } ]
// }
// バリューだけのオブジェクトの配列に変換する
console.log(Array.from(group.values()));// 上記の期待する結果
// おまけ キーだけにしたりもできる
console.log(Array.from(group.keys()));
// [
// [Function: pilot],
// [Function: support],
// [Function: fight],
// [Function: quiet]
// ]
まとめ
キー・バリューの扱いがしやすくバリューのみの配列にできるところが気に入っています。
今回はファンクションをキーにしました。Mapだとこういうこともできるんですね。
実際には文字列や数値をキーにする方が多そうです。
間違いや不明点等あればご指摘ください。