げきむずデータも怖くない！JavaScriptのオブジェクト配列変換の方法

## はじめに
DBやAPIから取得したデータを扱う際、配列を別の配列にしたり、配列からオブジェクトを生成したり、ということがあるかと思います。

今回はオブジェクトの配列にフォーカスして、どのように別の配列やオブジェクトを生成するか、ということを確認します。

本記事内では「TypeScript」を扱っていますが、JavaScriptでも使えるメソッドになります。
        
## オブジェクトの配列から、別の配列を生成する
### 概要
```typescript
// ユーザー型の定義
interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}
// ユーザーデータ
const users: User[] = [
  { id: 1, name: "田中太郎", email: "tanaka@example.com", age: 28 },
  { id: 2, name: "佐藤花子", email: "sato@example.com", age: 35 },
  { id: 3, name: "鈴木一郎", email: "suzuki@example.com", age: 42 },
];
```
上記のようなユーザーデータが格納された配列から、`name`だけを取り出して、別の配列を生成する方法を考えます。

### 対応方法
配列から新しい配列を生成するには、`map`メソッドを使用します。
```typescript
const userNames: string[] = users.map((user) => user.name);
```
`map`メソッドは引数として関数を受け取ります。
この関数は3つの引数を受け取りますが、ほとんどの場合1つめしか使いません。
そのため、2つめ、3つめの引数の役割については省略します。

引数の1つめは配列のデータです。ここでは`users`のデータ、つまりオブジェクトが一つずつ渡されます。

そして、関数の戻り値が新たな配列の値として設定されます。
ここでは`user.name`を返しているので、新たに生成された配列`userNames`は`user.name`の配列となります。

今回は単純な処理ですが、もっと複雑に値を加工することもできます。

配列から配列を生成するときは`map`、と覚えておきましょう。

## オブジェクトの配列から、単一のオブジェクトを生成する
### 概要
以下のようなオブジェクトの配列を考えます。
```typescript
// ユーザー型の定義
interface FunctionControl {
  id: number;
  functionName: string;
  enable_create: number;
  enable_read: number;
  enable_update: number;
  enable_delete: number;
}
// ユーザーデータ
const functionControls: FunctionControl[] = [
  {
    id: 1,
    functionName: "user",
    enable_create: 1,
    enable_read: 1,
    enable_update: 0,
    enable_delete: 0,
  },
  {
    id: 2,
    functionName: "item",
    enable_create: 0,
    enable_read: 1,
    enable_update: 1,
    enable_delete: 0,
  },
  {
    id: 3,
    functionName: "customer",
    enable_create: 0,
    enable_read: 1,
    enable_update: 1,
    enable_delete: 0,
  },
];
```
機能名(functionName)と、その機能において作成、読取、更新、削除を有効化するか、の設定値(enable_~の各項目)を持ちます。

このままだと`customer`の`enable_create`を確認したい場合、少し不便です。
```typescript
{
  customer: {
    enable_create: 0,
    enable_read: 1,
    enable_update: 1,
    enable_delete: 0,
  },
};
```
こんな形式のオブジェクトであれば、各機能ごとの有効化状況を簡単に取得できます。

### 対応方法
配列からオブジェクトなどの単一の要素を生成するには`reduce`メソッドを使用します。
```typescript
  const functionControlObj = functionControls.reduce((acc, curr) => {
    acc[curr["functionName"]] = {
      create: curr["enable_create"],
      read: curr["enable_read"],
      update: curr["enable_update"],
      delete: curr["enable_delete"],
    };
    return acc;
  }, {} as Record<string, Record<string, number>>);
```
`reduce`メソッドは第一引数に関数を、第二引数に初期値を設定します。
第一引数に設定する関数は、最大で4つの引数を受け取りますが、よく使うのは1つめと2つめです。
1つめの引数には、初期値から蓄積された値が設定されます。
2つめの引数には、配列の値が設定されます。

例えば、今回のデータで行くと、
まず初めの`acc`は初期値に設定した空のオブジェクト`{}`が設定されています。
そして、`curr`には`functionControls`の1番目のオブジェクトが設定されています。

`acc`（空のオブジェクト）のプロパティとして、`curr`（1番目のオブジェクト）の`functionName`を設定し、その値として`enable_~`のオブジェクトを設定しました。
```typescript
{
  customer: {
    create: 0,
    read: 1,
    update: 1,
    delete: 0,
  },
};
```
こんな感じのオブジェクトを生成して、`acc`に設定しているということです。

これを繰り返すことで、
```typescript
{
  customer: { create: 0, read: 1, update: 1, delete: 0 },
  item: { create: 0, read: 1, update: 1, delete: 0 },
  user: { create: 1, read: 1, update: 0, delete: 0 },
};
```
このようなオブジェクトを生成することができます。

配列から単一の要素を生成する際は`reduce`と覚えておきましょう。

## まとめ
`map`、`reduce`を適切に使うことで、配列を扱いやすい形に加工することができます。
個人的に`reduce`は若干使いにくさを感じますが、慣れれば便利だなと思いました。

ほかにも`fromEntries`を使う方法もあるのですが、それはまた別の機会に紹介します。