JSのMapオブジェクト グループ分けに使えそう。

# はじめに
Mapオブジェクトを使ったことない人が、これ使えるかもと思える記事です。
詳細には説明しません。
[グループ分けだけを見たい人はこちら](#mapオブジェクトを使ってグループ分け)

# Mapオブジェクト
連想配列を管理するオブジェクトです。
下記のように使います。これ便利だろうか？よくわからん。

```javascript

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' ]
// }
```

# オブジェクトリテラルでもやってみる
ほぼ同じことができます。
この場合はサイズが取れません。
```javascript
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は戦闘時の動作をファンクションとして定義したプロパティです。
``` js
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が同じメンバーでグループを作るとします。
こんな感じにメンバーが分かれてくれると嬉しいです。
```js
// 期待する結果
[
  [ { 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オブジェクトを使うと便利です。

```javascript
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だとこういうこともできるんですね。
実際には文字列や数値をキーにする方が多そうです。

間違いや不明点等あればご指摘ください。

## 参考文献
[改訂3版JavaScript本格入門 ～モダンスタイルによる基礎から現場での応用まで　山田祥寛　著](https://gihyo.jp/book/2023/978-4-297-13288-0)