🙆

【Ruby学習記録】配列の繰り返し処理

2022/09/11に公開

お題1:下記の配列の各要素を 2 で割った数字を全て足し合わせて、その結果を出力せよ

example.rb
numbers = [10000, 2500, 7000, 500]
answer.rb
numbers = [10000, 2500, 7000, 500]

sum = 0

numbers.each do |number|
  sum += number / 2
end

puts sum
===
$ ruby answer.rb
10000

または、下記のようにワンライナーで書くのもアリ。

answer.rb
numbers = [10000, 2500, 7000, 500]

puts numbers.map{|number| number / 2}.sum

Ruby で配列に対して繰り返し処理を行う場合、eachメソッドが基本になる。

配列名.each do |取り出した要素を格納する変数名|
  # ここに繰り返したい処理
end

JavaScript とかだと似たような形式で繰り返し処理を書くのでさほど違和感はないかもしれないが、PHP とかとは大分スタイルが変わってくるので、ちょっと慣れが必要。
*C とか PHP だと「繰り返し構文」というのがあり、それを使って書くのが基本になってくる。

foreach 配列名 as 取り出した要素を格納する変数名
  # ここに繰り返したい処理
endforeach

が、Ruby の場合は、Array クラスのメソッドにeachmapなどの繰り返し系メソッドがある、という位置づけになる。(一応、for 文や while 文もあるにはあって、そちらは C や PHP のスタイルに近い書き方も可能)
あくまでもメソッドなので戻り値が返ってくるものもあり、それをさらに処理という、慣れないとかなりトリッキーに感じる表現が出てくる。(このお題の別解みたいに)

お題2:下記の配列に1〜12月の英語表記が入っている。これをもとに"英語で1月は January です。"のように出力せよ

example.rb
months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
answer.rb
months = ["January","Febrary","March","April","May","June","July","August","September","October","November","December"]

months.each.with_index(1) do |month, index|
  puts "英語で#{index}月は#{month}です。"
end

Ruby でeachメソッドなどで繰り返しを行う場合、with_indexというメソッドを合わせて使うことで、繰り返し処理内でカウントアップするインデックス変数が使えるようになる。
一応、with_indexは Enumerator クラス(Array の親クラス)のインスタンスメソッドという扱いになっているが、ちょっと挙動が特殊。
通常、[インスタンス].[メソッドA].[メソッドB]と書くと、メソッド A の戻り値に対して、メソッド B を実行する、という順序で処理されることになる。
が、with_indexメソッドの場合は、each メソッドの結果を受けて動くのではなく、each メソッドに直接関与してインデックス変数を使えるようにすることになるので、with_index「メソッド」といわれると逆に理解が難しいかもしれない。
こういう、繰り返しメソッドのオプション的に使えるものもある、という位の理解でも良いのかも。

ただ、PHP の foreach などだとインデックス変数が使えないのと比べるとずいぶん使い勝手が良い。

example.php
months = ["January","Febrary","March","April","May","June","July","August","September","October","November","December"];

index = 1;
foreach months as month
    echo '英語で'.$index.'月は'$month'です。';
    index++;
endforeach

PHP だと、上のように、ループの外でインデックス変数を初期化しておかないといけないし、カウントアップの処理も書かないといけない。
*カウントアップを書き忘れて、意図通りに動かない、というのは結構あるあるネタかも。

GitHubで編集を提案

Discussion