【Ruby】配列の要素を交互に取得する。

# 目的
配列の要素を交互に取得し、二つの配列を作成します。
色々なやり方があるとは思いますが、私はこのような方法をとりました。

別解をいただきました。

- [@scivola 様よりご教示いただいた別解(配列が偶数の場合)](#scivola-様よりご教示いただいた別解)
- [@jnchito 様よりご教示いただいた別解(更にシンプルな方法)](#jnchito-様よりご教示いただいた別解)

# 方法

```ruby
array = ['い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を']

array_A = []
array_B = []

array.each_with_index { |kana, index| index.even? ? array_A << kana : array_B << kana }

p array_A
# => ["い", "は", "ほ", "と", "り", "る"]
p array_B
# => ["ろ", "に", "へ", "ち", "ぬ", "を"]
```

## 使用したメソッド

| メソッド | 意味 | マニュアル |
|:---:|:---|:---:|
| [each_with_index](#each_with_index) | 各要素とそれに付随する添字(インデックス)に対し処理を繰り返す | [Enumerable#each_with_index](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_index.html) |
| [even?](#even) | 要素が偶数であればtrueを返す | [Integer#even?](https://docs.ruby-lang.org/ja/latest/method/Integer/i/even=3f.html) |
| [? :](#--条件演算子) | 条件演算子(三項演算子) if・else文を1行で書いたもの | [演算子式](https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#cond) |
| [<<](#-追加) | 配列に要素を追加する | [Array#<<](https://docs.ruby-lang.org/ja/latest/method/Array/i/=3c=3c.html) |

## 解説

まず、空の配列を準備します。

```ruby
array_A = []
array_B = []
```
この中に元の配列`array`から交互に要素を入れていきます。
そのために使ったメソッドが`each_with_index`です。

### each_with_index

このメソッドは繰り返しを行う`each`メソッドに変数として各要素のインデックスを使用できるようにしたものです。

```ruby
['い', 'ろ', 'は'].each_with_index { |kana, index| p "#{kana} - #{index}" }
# => "い - 0"
#    "ろ - 1"
#    "は - 2"
```

配列`array`の各要素とインデックスは,

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| い | ろ | は | に | ほ | へ | と | ち | り | ぬ | る | を |

となっているため、これを利用して、インデックスが偶数の時には`array_A`に、奇数の時には`array_B`に要素を入れていきます。

条件分岐には条件演算子を使用しました。

### ? : 　(条件演算子)

`?`の前の条件で分岐し、`:`の前後で、trueの場合とfalseの場合それぞれの処理を分けています。

```ruby
num = 1

num == 1 ? "これは 1 です" : "これは 1 ではありません"
# => "これは 1 です"
```

これは、

```ruby
num = 1

if num == 1
  "これは 1 です"
else
  "これは 1 ではありません"
end
# => "これは 1 です"
```

と同じ意味になります。

そして、条件の偶数であるかどうかを確認するため、`even?`メソッドを使用しました。

### even?

このメソッドはレシーバ(.の左側)が偶数であれば`true`を、奇数であれば`false`を返してくれます。

```ruby
2.even?
# => true

1.even?
# => false

# 0も偶数です
0.even?
# => true
```

ちなみに、演算子を使用した計算でも同じことができます。

```ruby
num = 2

num % 2 == 0
# => true
```

ある数を2で割った時、余りが0であれば偶数です。

`even?`でインデックスが偶数か奇数かを確認し、`? :`で条件分岐したあとは、
`<<`で配列に要素を足しています。

### << (追加)

`<<`は配列の末端に要素を一つ追加します。

```ruby
num_array = [1, 2]

num_array << 3

p num_array
# => [1, 2, 3]
```

<br>
<br>

# @scivola 様よりご教示いただいた別解

※ 配列が偶数の場合のみです。

```ruby
array = ['い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を']

array_A, array_B = array.each_slice(2).to_a.transpose

p array_A
# => ["い", "は", "ほ", "と", "り", "る"]
p array_B
# => ["ろ", "に", "へ", "ち", "ぬ", "を"]
```

## 使用したメソッド

| メソッド | 意味 | マニュアル |
|:---:|:---|:---:|
| [each_slice](#each_slice) | 要素を指定の数づつ分ける | [Enumerable#each_slice](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_slice.html) |
| [to_a](#to_a) | 配列を作る | [Enumerable#entries](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/entries.html) |
| [transpose](#transpose) | 配列を行列に見立て、行と列を入れ替える | [Array#transpose](https://docs.ruby-lang.org/ja/latest/method/Array/i/transpose.html) |


## 解説

今回はメソッドで配列が作られるため、空の配列を作る必要はありません。

まず、`array_A, array_B =`。
これは**多重代入**([マニュアル](https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#multiassign))を使用しています。

```ruby
num_A, num_B = 1, 2

p num_A
# => 1

p num_B
# => 2
```

このように、左辺と右辺を2つずつ用意することで、同時に代入が可能になります。
この2つの左辺に代入できる、2つの配列を作っていきます。

まず`each_slice(2)`を使用し、配列を2つずつの塊に分けています。

### each_slice

このメソッドは複数の要素(配列や範囲オブジェクト)を、`()`内で指定した数ずつブロック( *{ }内* )に渡します。

```ruby
[1, 2, 3, 4, 5, 6].each_slice(2) { |n| p n }
# [1, 2]
# [3, 4]
# [5, 6]
```
元の配列を二つずつに分けたら、次はそれを配列にしなければなりません。そのために使用するメソッドが`to_a`です。

### to_a

このメソッドは、渡された要素を配列に変換します。

```ruby
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```
上記は連続する(`..`)、1〜10までの数字を配列に変換しています。

`each_slice`は、`{}`をなくすと、`Enumerator`クラスのオブジェクトを返します。

```ruby
[1, 2, 3, 4, 5, 6].each_slice(2)
# => #<Enumerator: [1, 2, 3, 4, 5, 6]:each_slice(2)>
```

`to_a`メソッドは`Enumerator`クラスのメソッドでもあるため、渡されたオブジェクトに使用し、配列が作成されます。

```ruby
aa = [1, 2, 3, 4, 5, 6].each_slice(2)

aa.class      # .classメソッドを使うと、レシーバ(.の左側)のクラスを返してくれます。
# => Enumerator

aa.to_a
# => [[1, 2], [3, 4], [5, 6]]
```

最後に、2つずつに分けた配列の中の配列を右側と左側で分ければ完了です。
つまり、上記の数字を例にすると、
［［ <font color='red'>1</font>, <font color='blue'>2</font> ］,［ <font color='red'>3</font>, <font color='blue'>4</font> ］,［ <font color='red'>5</font>, <font color='blue'>6</font> ］］
のように<font color='red'>赤の数字の配列</font>と<font color='blue'>青の数字の配列</font>に分けることができれば、元の配列を交互に取得して、二つの配列を作成したことになります。

そのためのメソッドが`transpose`です。

### transpose

このメソッドは配列の中の配列を行列に見立て、行と列を入れ替えます。

```ruby
[[0, 1], [0, 1], [0, 1]].transpose
# => [[0, 0, 0], [1, 1, 1]]
```

先程の<font color='red'>赤</font>と<font color='blue'>青</font>の数字で例えると、

| <font color='red'>赤</font> | <font color='blue'>青</font> |
|:---:|:---:|
| <font color='red'>1</font> | <font color='blue'>2</font> |
| <font color='red'>3</font> | <font color='blue'>4</font> |
| <font color='red'>5</font> | <font color='blue'>6</font> |

が、

| <font color='red'>赤</font> | <font color='red'>1</font> | <font color='red'>3</font> | <font color='red'>5</font> |
|:---:|:---:|:---:|:---:|
| <font color='blue'>青</font> | <font color='blue'>2</font> | <font color='blue'>4</font> | <font color='blue'>6</font> |

となるようなイメージです。

これで2つの配列ができたため、多重代入でそれぞれの変数に代入されます。

<br>
<br>

# @jnchito 様よりご教示いただいた別解

```ruby
array = ['い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を']

array_A, array_B = array.partition.with_index { |_, index| index.even? }

p array_A
# => ["い", "は", "ほ", "と", "り", "る"]
p array_B
# => ["ろ", "に", "へ", "ち", "ぬ", "を"]
```
## 使用したメソッド

| メソッド | 意味 | マニュアル |
|:---:|:---:|:---:|
| [partition](#partition) | 各要素を条件分岐し、2つの配列を作成する。 |[Enumerable#partition](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/partition.html) |
| [with_index](#with_index) | 繰り返し処理の変数に、インデックスが使えるようになる。 | [Enumerator#with_index](https://docs.ruby-lang.org/ja/latest/method/Enumerator/i/with_index.html) |
| [even?](#even-odd) | 要素が偶数であればtrueを返す | [Integer#even?](https://docs.ruby-lang.org/ja/latest/method/Integer/i/even=3f.html) |

## 解説

今回もメソッドで配列が作られるため、変数に配列の定義は必要ありません。
さらに[多重代入](#解説-1)で、2つの配列を同時に代入します。

そして、その二つの配列を作るためのメソッドが`partition`です。

### partition

このメソッドは、配列の各要素をブロック( *{ }内* )の条件を満たすか否かで2つの配列に分けます。

```ruby
[1, 2, 3, 4, 5].partition { |num| (num % 2) == 0 }
# => [[2, 4], [1, 3, 5]]
```

このメソッドを使用して、偶数の場合とそれ以外(奇数)の場合の配列を作ります。

しかし、`partition`メソッドが使用できるブロックの変数は、要素の変数しか使用できません。（上記の場合、`num`の部分）
今回、偶数・奇数を判断したいのは要素に付随する添字(`index`)の値です。

そのために必要になるメソッドが`with_index`です。

### with_index

このメソッドは、本来`index`が変数として使用できない繰り返し処理(`map`メソッド等)に、`index`を使用できるようにするものです。

```ruby
['い', 'ろ', 'は'].map.with_index { |kana, index| "#{index}-#{kana}" }
# => ["0-い", "1-ろ", "2-は"]
```

これを利用して、`index`が偶数の場合と奇数の場合を`even?`で判断し、2つの配列を作成します。

### even? (odd?)

このメソッドは[先も出た](#even)通り、レシーバ(.の左側)が偶数であれば`true`を、奇数であれば`false`を返してくれます。

ちなみに、`odd?`というメソッドもあり、これは`even?`の逆になります。
レシーバが奇数であれば`true`を、偶数であれば`false`を返してくれます。

```ruby
1.odd?
# => true

2.odd?
# => false
```

### 変数 _

今回、`partition.with_index`のブロックで使用する変数は`index`のみで、要素は使用しません。そのため、要素の変数を`_`にしています。

```ruby
array.partition.with_index { |_, index| index.even? }
```
参考：[変数名やブロックパラメーターをアンダースコア1文字にするイディオム - Qiita](https://qiita.com/jnchito/items/3cce0c057f54afa29d0a)

<br>
<br>

# 最後に

さらに良い方法がございましたら、ご教示いただけますと幸です。
ご覧いただき、ありがとうございました。