Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"FOR LOOP": "forループ",
"ARRAYS": "配列",
"ARRAY FILTERING": "配列のフィルター",
"ARRAY REDUCE": "配列のreduce",
"ACCESSING ARRAY VALUES": "配列の値にアクセスする",
"LOOPING THROUGH ARRAYS": "配列をループする",
"OBJECTS": "オブジェクト",
Expand Down
1 change: 1 addition & 0 deletions menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"PROMISE ALL",
"ASYNC AWAIT",
"ARRAY FILTERING",
"ARRAY REDUCE",
"ARRAYS MORE",
"FETCH",
"FIZZBUZZ",
Expand Down
82 changes: 82 additions & 0 deletions problems/array-reduce/problem_ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
配列に対する処理で、結果を順々に蓄積していきたい時があります。

このような処理では `.reduce()` メソッドが便利です。

`reduce` のコールバックでは、第一引数に「これまでの結果」が渡されます。
この第一引数は `acc` と書くことが多く、`accumulator` (蓄積していく値) の略です。
第二引数には「現在の要素」が渡され、こちらは `cur` (`current value` の略) と書くことがよくあります。

まずは文字列で、`acc` と `cur` の流れを見てみましょう。

```js
const letters = ["A", "B", "C"];
const joined = letters.reduce((acc, cur) => acc + cur, "");

console.log(joined); // "ABC"
```

この時、内部では次のように値が渡されます。

- 1回目: `acc = ""`, `cur = "A"` → 次の `acc` は `"A"`
- 2回目: `acc = "A"`, `cur = "B"` → 次の `acc` は `"AB"`
- 3回目: `acc = "AB"`, `cur = "C"` → 最終結果は `"ABC"`


少し応用した使い方になりますが、`reduce` は数値の合計だけでなく、関数を順番に適用する「関数パイプライン」のような使い方もできます。
関数も値なので、配列の要素に入れられます。

例えば次のコードでは、`steps` に入った関数を先頭から順番に実行していきます。

```js
const plus2 = (x) => x + 2;
const multiple3 = (x) => x * 3;
const minus1 = (x) => x - 1;

const steps = [plus2, multiple3, minus1];
const initialValue = 5;

const result = steps.reduce((acc, fn) => fn(acc), initialValue);

console.log(result); // 20
```

この例だと、内部では次のように関数が実行されていきます。
1回目: `plus2(5)`
2回目: `multiple3(7)`
3回目: `minus1(21)`
このようなケースでは配列の順番によっては、結果が変わることも覚えておいてください。


## やってみよう

`array-reduce.js` ファイルを作りましょう。

ファイルの中で、以下の初期ユーザー情報(オブジェクト)を定義しましょう。

```js
const userInfo = {
name: "Taro",
age: 18,
};
```

そして、引数のオブジェクトに、下記のような各属性情報を追加してreturnするような関数を作ってください。
1. `user.age >= 20`なら、`category`という属性に `"adult"`を、そうでないなら `"minor"`を設定する関数
2. `isActive`という属性に`true`を追加する関数
3. `greeting`という属性に `"Hello " + user.name`の文字列を設定する関数

例えば、`isActive`については以下のような関数を用意するのがよいでしょう
```js
const addIsActiveFlag = (user) => {
return { ...user, isActive: true };
};
```

最後に`reduce` を使って、`userInfo` を初期値として関数を先頭から順番に適用し、全部の属性を追加した情報を作ってください。
そして `console.log(result)` を実行して、標準出力に表示しましょう。

次のコマンドを実行し、あなたのプログラムが正しく動くか確認しましょう。

```bash
javascripting verify array-reduce.js
```
7 changes: 7 additions & 0 deletions problems/array-reduce/solution_ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 関数パイプラインを作れました!

いいですね。`reduce` で関数を順番に適用し、値を蓄積できましたよ。

次の課題に挑戦しましょう。

コンソールで `javascripting` コマンドを実行します。次の課題を選択しましょう。
23 changes: 23 additions & 0 deletions solutions/array-reduce/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const userInfo = {
name: "Taro",
age: 18,
};

const addCategory = (user) => {
const category = user.age >= 20 ? "adult" : "minor";
return { ...user, category };
};

const addIsActiveFlag = (user) => {
return { ...user, isActive: true };
};

const addGreeting = (user) => {
return { ...user, greeting: "Hello " + user.name };
};

const steps = [addCategory, addIsActiveFlag, addGreeting];

const result = steps.reduce((acc, fn) => fn(acc), userInfo);

console.log(result);