【挑戦状の正解発表＆解説】配列の要素を増やすには？〜面白解答も紹介〜

# 先日、Twitter上でこんなクイズを出題しました

↓こちらです。

https://twitter.com/yumemiinc/status/1560086874303082497?s=20&t=Z-6OQD7Cb7eVGNaw3hAmbg

### この記事では、クイズの正解発表をして行きます。

# クイズの内容

クイズの内容は以下です。

### 【JSクイズ】
`/* ここに回答を書いてください */` の部分を埋めてくださいやで！


```ts
const array1 = [1, 2, 3, 4, 5, 6]
const array2 = array1./* ここに解答を書いてください */

console.log(array2)
// -> [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]
```

---

要は、

> `[1, 2, 3, 4, 5, 6]`という配列から
> `[1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]`という配列を生成するには
> どうすればいいのか？

という問題です。

もう少し要約すると、

> `array1`という配列の各要素をチェックして、
> **奇数**なら**3つ**に増やすべし！
> **偶数**なら**2つ**に増やすべし！
> そして`array2`という変数に格納すべし！

↑こんな問題です。

# 正解発表

それでは正解を発表いたします。

いろんな書き方がありますが、私が想定していた模範解答は以下です。

```ts
const array2 = array1.flatMap(n => n % 2 ? [n, n, n] : [n, n])
```

`flatMap()`というメソッドを見たことがない方は「なんやこれ？」と感じるかもしれません。
順を追って解説して行きます。

# 解説



まず、今回やりたいことは

> `array1`という配列の各要素をチェックして、
> **奇数**なら**3つ**に増やすべし！
> **偶数**なら**2つ**に増やすべし！
> そして`array2`という変数に格納すべし！

↑こうでしたね。

「`array1`という配列をもとに、`array2`という配列を作る」必要があります。

ということは、`map()`メソッドが使えそうですね。

`map()`メソッドを使って、
とりあえず、配列の全ての要素を**2つに増やして**みましょう。

```ts
const array2 = array1.map(n => [n, n])
```

↑配列内の各要素を、全て**2個入りの配列**にしてあげる感じです。

すると、出力結果は以下のようになります。

```ts
console.log(array2)
// => [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6]]
```

↑当然、**二重の配列**になってしまいます。
なので、最後に`flat()`してあげます。

```ts
const array2 = array1.map(n => [n, n]).flat() // <- .flat() 追加！
```
↑こうですね。
すると、出力結果は以下のようになります。

```ts
console.log(array2)
// => [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]
```

↑二重の配列を、フラットな配列にすることができました。
結果として、全ての要素を**2個に増やす**ことができました。


# `flatMap()`メソッドを使ってみよう

上記のように

> `map()`してから`flat()`したい

そんなときに`flatMap()`メソッドが使えます。


```ts
const array2 = array1.flatMap(n => [n, n])

console.log(array2)
// => [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]
```

↑こうですね。

つまり`flatMap()`メソッドとは

```ts
n => [n, n]
```

↑このような関数を渡すことで、
**配列の要素を増やす**ことができるメソッドと言えます。

### ちなみに

`flatMap()`メソッドに対して、

```ts
n => []
```

↑こういう関数を渡せば、**要素を減らす**（取り除く）こともできます。

# クイズ解説の続き

```ts
const array2 = array1.flatMap(n => [n, n])

console.log(array2)
// => [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]
```

とりあえず、配列の要素を全部**2個に増やす**ことができました。

あとは、

> **奇数**なら**3つ**に増やすべし！
> **偶数**なら**2つ**に増やすべし！

↑この**条件分岐**が必要ですね。

「奇数なのか偶数なのか」を調べるには、以下の式を使います。

```ts
n % 2
```

**剰余演算子**（`%`）を使う感じですね。

「`n`を`2`で割った**余り**」を求めるということです。

- `n`を`2`で割った**余り**が
    - `1`であれば、`n`は**奇数**
    - `0`であれば、`n`は**偶数**

という感じです。

※`n % 2`の結果は、`1`か`0`のどちらかになります。`2`とか`5`とかにはなりません。（当たり前か）

コードにすると、

```ts
if (n % 2 === 1) {
    // 奇数の場合の処理
} else {
    // 偶数の場合の処理
}
```

↑こんな風に書けそうですね。

# 条件に応じて、配列の要素を増やすべし

先ほどは、`flatMap()`メソッドに対して、

```ts
n => [n, n]
```

↑この関数を渡すことで、配列の各要素を**2個ずつに増やす**ことができました。

ここに「奇数かどうか」という条件を加えたいので・・・

```ts
n => {
    if (n % 2 === 1) {
        // 奇数だったら3つ！
        return [n, n, n]
    } else {
        // 偶数だったら2つ！
        return [n, n]
    }
}
```

↑こんな関数を書いてみます。
この関数を`flatMap()`メソッドに渡してあげれば、

> **奇数**なら**3つ**に増やすべし！
> **偶数**なら**2つ**に増やすべし！

↑この条件を満たせそうです。

三項演算子を使って、1行で書くと・・・

```ts
n => n % 2 === 1 ? [n, n, n] : [n, n]
```

↑こうですね。

`n % 2 === 1`という条件は、
今回の場合`n % 2`と書いても大丈夫なので、

```ts
n => n % 2 ? [n, n, n] : [n, n]
```

↑これでもOKです。

では、この関数を`flatMap()`メソッドに渡してみましょう。

```ts
const array1 = [1, 2, 3, 4, 5, 6]
const array2 = array1.flatMap(n => n % 2 ? [n, n, n] : [n, n])

console.log(array2)
// -> [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]
```

出力したかった内容を、無事に出力することができました。

模範解答の解説は以上です。

# 別解

こんな解答をしてくださった方もいました。

https://twitter.com/cuttlefish_math/status/1560236022625357824?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

メインの処理としては、

```ts
const array2 = array1.flatMap((x) => Array(x % 2 + 2).fill(x))
```

↑こうですね。

`flatMap()`メソッドに対して

```ts
(x) => Array(x % 2 + 2).fill(x)
```

↑こんな関数を渡しています。

`x % 2 + 2`という式がスマートで「頭いいな〜！」と思いました。

- `x % 2`は
    - `x`が**奇数**であれば`1`になる
    - `x`が**偶数**であれば`0`になる

↑この法則を利用して、
そこに`2`を足してやることで

- `x % 2 + 2`は
    - `x`が**奇数**であれば`3`になる
    - `x`が**偶数**であれば`2`になる

↑こういうことをやってるわけですね・・・！

つまり`Array(x % 2 + 2)`の部分は、
`Array(3)`または`Array(2)`として機能するわけです。

そうやって、長さを指定した配列を生成して、
`fill()`メソッドで埋めてあげる、と。

ワイじゃ一生思いつかへんわ・・・


ていうか`Array()`って`new`つけなくてもいいんですね・・・！
これも知りませんでした。

クイズ1問でこんなに勉強させてもらって、お得な気分・・・！


# 面白解答もたくさん

面白解答も沢山いただきました。

## 面白解答その1

https://twitter.com/shindy_JP/status/1560245331778236417?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### メインの処理

```ts
const array2 = array1.concat(1, 1, 2, 3, 3, 4, 5, 5, 6).sort()
```

### いや`array1`に足りない内容を足して`sort()`すんのかい！

ちょっと強引な気もしますが、ルール上は正解ですね・・・！

## 面白解答その2

https://twitter.com/D_drAAgon/status/1560261919659139073?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### メインの処理

```ts
const array2 = array1.slice(6).concat([1,1,1,2,2,3,3,3,4,4,5,5,5,6,6]);
```

### いや`array1`の要素たちの立場！
### 丸ごと入れ替わっとるやないかい！
### っていうか、出力したい配列をベタ書きしとるやないかい！



でも、ルール上は正解ですね・・・！



## 面白解答その3

https://twitter.com/uhyo_/status/1560109480062652416?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### メインの処理

```ts
const array2 = array1.concat(array1, array1).reduce((a,b,c,d)=> 
  (d.push(...d.splice(Number(a%16n),1)),a >> 4n||d),4721443915042874085729n).slice(0, 15);
```

### いや難読の極み！


でも、実行してみたら正解でした・・・！
さすが@uhyo大先生・・・！




## 面白解答その4

https://twitter.com/fuwasegu/status/1560267913973870593?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### いやユーザーの判断で配列に追加すんのかい！
### 何回ボタン押さすねん！
### っていうか、アルゴリズムを「運用でカバー」すな！

でも、正解っちゃ正解なのか・・・？



## 面白解答その5

https://twitter.com/yusuke/status/1560176286974492672?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### メインの処理

```ts
const array2 = array1.length;const 待避 = console.log;console.log=function(){待避("[1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]")}
```

### いや一行に何文書くねん！
### そして`console.log()`メソッドを上書きって！

でも「セミコロン禁止」ってルールに書いてなかったしなぁ。。。
正解ということになるのか・・・？


## 面白解答その6

https://twitter.com/Yametaro1983/status/1560104149102239749?s=20&t=fe51-vqoXg-J-wJT8FJ5Gg

### メインの処理

```ts
const array2 = array1.unko || [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]
```

### いや頼むから`array1`の中身を使ってあげて！
### （ワイ自身の解答ですが）

# 総括

最後は大喜利大会みたいになっていましたが、
数百名もの方々が解答してくださり、かなり盛り上がりました。

出題者である私自身も、

> 「え、こんな書き方もあるんかい！」

と、とても勉強になりました。

ご参加いただいた皆さま、ありがとうございました！

## もしよかったらご挑戦ください

もしかすると、まだまだ他の解答もあるかも知れません。

TypeScriptのプレイグラウンドを用意してありますので、
よかったら挑戦してみてください。

そして面白解答が思い浮かんだら教えてください・・・笑

https://twitter.com/Yametaro1983/status/1560091681042857985?s=20&t=Ixp1wzr_pmZ_Cr_CeD4gag

# 新しい記事もよろしくやで！

- [「技術記事って、別に書かなくてもよくないすか？」](https://qiita.com/Yametaro/items/1f096e08e7a387ae3792)