概要
flatMap
はES2019で追加された機能で比較的新しい配列を操作するメソッドです。
MDNを見ると使用例に以下のようなものがあります。
const arr1 = [1, 2, [3], [4, 5], 6, []];
const flattened = arr1.flatMap(num => num);
console.log(flattened);
// Expected output: Array [1, 2, 3, 4, 5, 6]
これだけ見るとただmapをflatにしただけであまり使い道がないように思いました。
しかし実際に使うと便利な場面が多々あるので紹介したいと思います。
要素の抽出
例えばユーザーの名前とペットの名前が書かれた配列があるとします。
ペットを飼っていない人もいるのでpetは定義されていないこともあります。
ここからpetの名前の配列を取り出す操作を考えたいと思います。
const users = [
{ name: 'user1', pet: 'pochi' },
{ name: 'user2', pet: 'tama' },
{ name: 'user3' }
];
// ここから [ 'pochi', 'tama' ]という配列が欲しい
この時従来であれば次のように記述します。
const pets = users.filter((user) => user.pet).map((user) => user.pet);
この書き方だと2回同じようなことを書かなければならず、わかりにくさがあります。
一方でflatMapを使うと以下のように記載できます。
users.flatMap((user) => user?.pet || [])
このようにobjectの配列から要素を抽出したいときに
flatMapを使うことでより簡潔に使うことができます。
要素を増やす
例えば、商品と金額のオブジェクトのリストが与えられるとします。
ここで商品がスマートフォンがあれば無料で保護シートをつけるという処理をしたいと考えます。
この時、表示の問題でただ末尾に保護シートを追加するのではなくスマートフォンの後に保護シートを追加したいとします。
const cart = [
{ name: '本', price: 1000 },
{ name: 'スマートフォン', price: 30000 },
{ name: '電池', price: 200 },
];
// ここから下記のような配列が欲しい
// const cart = [
// { name: '本', price: 1000 },
// { name: 'スマートフォン', price: 30000 },
// { name: '保護シート', price: 0 },
// { name: '電池', price: 200 },
// ];
この時従来であれば次のように記述します。
const newCart = carts.reduce((newCart, item) => {
newCart.push(item);
if (item.name === 'スマートフォン') {
newCart.push({ name: '保護シート', price: 0 });
}
return newCart;
}, []);
reduceを使うことで記載しましたが若干コードの長さや可読性が気になります。
flatMapを使うことで以下のように記載できます。
const newCart = cart.flatMap((item) =>
item.name === 'スマートフォン' ?
[item, { name: '保護シート', price: 0 }] : item
);
かなり簡潔に記載することができました。
まとめ
flatMapはただflatにするだけでなく
要素を増やしたり抽出したりしたい時に使える
とても便利なメソッドです!