はじめに
DBやAPIから取得したデータを扱う際、配列を別の配列にしたり、配列からオブジェクトを生成したり、ということがあるかと思います。
今回はオブジェクトの配列にフォーカスして、どのように別の配列やオブジェクトを生成するか、ということを確認します。
本記事内では「TypeScript」を扱っていますが、JavaScriptでも使えるメソッドになります。
オブジェクトの配列から、別の配列を生成する
概要
// ユーザー型の定義
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
メソッドを使用します。
const userNames: string[] = users.map((user) => user.name);
map
メソッドは引数として関数を受け取ります。
この関数は3つの引数を受け取りますが、ほとんどの場合1つめしか使いません。
そのため、2つめ、3つめの引数の役割については省略します。
引数の1つめは配列のデータです。ここではusers
のデータ、つまりオブジェクトが一つずつ渡されます。
そして、関数の戻り値が新たな配列の値として設定されます。
ここではuser.name
を返しているので、新たに生成された配列userNames
はuser.name
の配列となります。
今回は単純な処理ですが、もっと複雑に値を加工することもできます。
配列から配列を生成するときはmap
、と覚えておきましょう。
オブジェクトの配列から、単一のオブジェクトを生成する
概要
以下のようなオブジェクトの配列を考えます。
// ユーザー型の定義
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
を確認したい場合、少し不便です。
{
customer: {
enable_create: 0,
enable_read: 1,
enable_update: 1,
enable_delete: 0,
},
};
こんな形式のオブジェクトであれば、各機能ごとの有効化状況を簡単に取得できます。
対応方法
配列からオブジェクトなどの単一の要素を生成するにはreduce
メソッドを使用します。
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_~
のオブジェクトを設定しました。
{
customer: {
create: 0,
read: 1,
update: 1,
delete: 0,
},
};
こんな感じのオブジェクトを生成して、acc
に設定しているということです。
これを繰り返すことで、
{
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
を使う方法もあるのですが、それはまた別の機会に紹介します。