PPAP で reduce の基本を理解する


プログラミングスクールに通う友人から JavaScript の reduce を易しく解説してほしいと言われたので、サンプルコードを書いてみました。

PPAP をネタにして、 ['Pen', 'Pineapple', 'Apple', 'Pen'] という配列から PPAP を作るというコードです。
今さらすぎてクソ恥ずかしいネタですが分かりやすいと好評だったので、そのへんは目をつむって読んでいただければありがたいです。

対象者

  • reduce って何?って人
  • reduce が None of 理解 って人

reduce の基本

基本的な考え方は、配列の要素から文字列や数値などの値に変えることです。

こちらをご覧ください。

Array.prototype.reduce() - MDN

さっそく解説

まずはピコ太郎を用意します。

const piko = ['Pen', 'PineApple', 'Apple', 'Pen'];

このピコ太郎を reduce してあげて PPAP を完成させましょう。

失敗例 1

MDN で reduce の基本構文を読むとこんな感じに書けますが、これは失敗です。
文字列をそのまま返しているから当然ですね。

※ ここでは accumulator を acc, currentIndex を cur と表記しています。

// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur;
});
console.log(ppap);

// 出力結果 -> 'PenPineAppleApplePen'

失敗例 2

では文字列の頭の 1 文字だけを取得して同じように処理してみましょう。
string[0] のようにすれば文字列の 0 番目の文字を取得できます。

// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc[0] + cur[0]; // 1 文字目を取得
});
console.log(ppap);

// 出力結果 -> 'PP'

なぜこのようになるのか解説します。

配列 piko を見てください。
reduce の基本として、 1 回目のループでは 0 番目の 'Pen' が acc になり、 1 番目の 'PineApple' が cur になります。
そして、それぞれ 1 文字目を取得するので acc は 'P' , cur は 'P' となり、それを足し合わせた PP が次のループの acc となります。

2 回目のループでは 'PP' が acc'Apple' が cur となるわけですが、ここで 1 文字目を取得するため、 acc である 'PP'P となり、 結果 PA が次のループの acc となるわけです。

本来は P -> PP -> PPA -> PPAP と足されてほしいのですが、毎回 1 文字目のみを取ってしまうため意図しないものになってしまっています。

では acc はそのまま使って、 cur だけ 1 文字目を取得したらどうなるでしょう。

失敗例 3

// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur[0]; // cur だけ 1 文字目を取得
});
console.log(ppap);

// 出力結果 -> 'PenPAP'

後半は良さそうですね。ですが、 1 回目のループで acc をそのまま使っているため Pen がそのままになってしまいました。
acc, cur の変更だけではどうにもならないようですので、 reduce の第2引数を使ってみましょう。

成功例

// 成功例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur[0];
}, ''); // 第2引数を指定
console.log(ppap);

// 出力結果 -> 'PPAP'

できました。
第2引数を指定すると、 1 回目のループの acc を指定することができます。
分かりやすく言い換えると、配列の -1 番目にこれを差し込むようなイメージです。

// イメージ

// reduce で第2引数入れる前のピコ太郎
const piko = ['Pen', 'PineApple', 'Apple', 'Pen'];

// reduce で第2引数入れたときのピコ太郎
const piko = ['', 'Pen', 'PineApple', 'Apple', 'Pen'];

番外編: ピコ太郎以外の用途

要するに頭文字を取ってつなげる処理なので、略したい単語があれば何でも使えます。

const tgif = "Thanks God It's Friday!";
const tgifArray = tgif.split(' '); // ["Thanks", "God", "It's", "Friday!"]

console.log(tgifArray.reduce((acc, cur) => acc + cur[0], ''));
// 出力結果 -> 'TGIF'
const diy = "Do It Yourself";
console.log(diy.split(' ').reduce((acc, cur) => acc + cur[0], ''));
// 出力結果 -> 'DIY'