こんにちは!じゃいごテックのあつしです。
今回はプログラミングの基本動作「逐次」「分岐」「反復」のうちのひとつ、反復(繰り返し処理)をご紹介します。
また、一緒に覚えておくと便利な機能についてもご紹介します。
決まった回数・範囲で繰り返す
timesメソッド
整数.times do |変数|
処理
end
0 から指定した回数 - 1 までカウントアップしながら繰り返し処理を行います。変数は省略可能です。
# 0,1,2 とカウントアップしながら3回繰り返す 3.times do |n| p "Hello! #{n}" end # > "Hello! 0" # > "Hello! 1" # > "Hello! 2" # こう書いても同じ 3.times { |n| p "Hello! #{n}"} # > "Hello! 0" # > "Hello! 1" # > "Hello! 2" # 変数は省略可 3.times { p "Hello!" } # > "Hello!" # > "Hello!" # > "Hello!"
eachメソッド
繰り返しオブジェクト.each do |変数|
処理
end
繰り返しオブジェクト先頭から次々に要素を参照して処理を行います。
# 範囲オブジェクトから要素を参照する (0..2).each do |n| p "Hello! #{n} " end # > "Hello! 0" # > "Hello! 1" # > "Hello! 2" # 配列から要素を参照する ["Taro", "Jiro", "Hanako"].each do |name| p "Hello! #{name}" end # > "Hello! Taro" # > "Hello! Jiro" # > "Hello! Hanako"
each_with_indexメソッド
繰り返しオブジェクト.each_with_index do |要素, インデックス|
処理
end
繰り返しオブジェクトから要素とそのインデックスを取り出して繰り返し処理を行います。
# 範囲オブジェクトの要素とインデックスを同時に取り出す ("a".."e").each_with_index do |char, index| p "#{char},#{index}" end # > "a,0" # > "b,1" # > "c,2" # > "d,3" # > "e,4"
with_indexメソッド (each.with_index)
繰り返しオブジェクト.each.with_index(開始値) do |要素, インデックス|
処理
end
繰り返しオブジェクトから要素と開始値からのインデックスを取り出して繰り返し処理を行います。
("a".."e").each.with_index(101) do |char, index| p "#{char},#{index}" end # > "a,101" # > "b,102" # > "c,103" # > "d,104" # > "e,105"
zipメソッド
繰り返しオブジェクト.zip(繰り返しオブジェクト,[繰り返しオブジェクト])
繰り返しオブジェクト自身と、引数で渡した配列の各要素を組にした配列を返します。
引数の要素数が多い場合は無視され、足りない場合は nil が代入されます。
name = ["Taro", "Jiro", "Hanako"] age = [25, 22, 23] hobby = ["fishing", "cycling", "piano"] p name.zip(age, hobby) # > [["Taro", 25, "fishing"], ["Jiro", 22, "cycling"], ["Hanako", 23, "piano"]]
条件を満たす間繰り返し続ける
while(制御構文)
while 条件式 do
処理
end
条件式が true の間繰り返し処理を行います(doは省略可)。主に繰り返し回数が事前に分からない時に使用します。
繰り返しを終了するための条件を間違えると無限ループになる可能性があるので注意しましょう。【 強制終了: ctrl+C 】
# 0 から 9 までカウントする count = 0 while count < 10 p count count += 1 end # > 0 # > 1 # > 2 # > 3 # > 4 # > 5 # > 6 # > 7 # > 8 # > 9 # この場合 count が 10 にならないので無限ループ # 実行してみる場合は Ctrl + C で停止して下さい count = 0 while count != 10 p count count += 4 end # > 0 # > 4 # > 8 # > 12 # > 16 # > 20, 24, ... 無限に続く
break・next
break(制御構文)
現在の繰り返し処理を脱出します。
# 0 から 9 まで表示するプログラムで # カウント (n) が 3 になったら反復を脱出 (0..9).each do |n| break if n == 3 p n end # > 0 # > 1 # > 2 n = 0 while n < 10 break if n == 3 p n n += 1 end # > 0 # > 1 # > 2
next(制御構文)
以後の処理をスキップして、現在繰り返し中の次のステップの処理を行います。
# 0 から 9 の中で奇数を表示、偶数はスキップ (0..9).each do |n| next if n.even? p n end # > 1 # > 3 # > 5 # > 7 # > 9 n = 0 while n < 10 next if n.even? p n n += 1 end # > 1 # > 3 # > 5 # > 7 # > 9
多重ループ
繰り返し処理の中に繰り返し処理を記述することを多重ループといいます。例えば2重ループで2次元配列、3重ループで3次元配列の全要素に次々とアクセスできます。
2重ループの例
ある中学校の各学年が3組ずつあるとして、1年1組から3年3組まで順番に出力してみる。
# 学年のループ (1..3).each do |nen| # 組のループ (1..3).each do |kumi| p "#{nen}年#{kumi}組" end end # > "1年1組" # > "1年2組" # > "1年3組" # > "2年1組" # > "2年2組" # > "2年3組" # > "3年1組" # > "3年2組" # > "3年3組"
多重ループを使ってpaiza練習問題を解いてみる
かけ算表 (paizaランク D 相当)
※ paiza レベルアップ問題集 条件分岐メニューより
問題:
配列 A の要素数 N とその要素 A_i (1 ≦ i ≦ N) が与えられるので、A についてのかけ算表 B を出力してください。かけ算表は N * N の二次元配列の形式とし、B の i 行 j 列の要素 B_ij について、B_ij = Ai * Aj (1 ≦ i , j ≦ N) が成り立つものとします。
例として、A = [1,2,3] のとき B は
1 2 3
2 4 6
3 6 9
となります。
入力される値
N A_1 ... A_N
- 1 行目では配列 A の要素数 N が与えられます。
- 2 行目では、A の各要素 A_i (1 ≦ i ≦ N) が半角スペース区切りで与えられます。
期待する出力
B_11 B_12 ... B_1N
... B_N1 B_N2 ... B_NN
A のかけ算表 B を出力してください。
条件
すべてのテストケースにおいて、以下の条件をみたします。
- 1 ≦ N ≦ 100 (1 ≦ i ≦ N)
- 0 ≦ A_i ≦ 100 (1 ≦ i ≦ N)
入力例1
3
56 37 30
出力例1
3136 2072 1680
2072 1369 1110
1680 1110 900
入力例2
10
72 10 75 15 16 65 7 43 96 57
出力例2
5184 720 5400 1080 1152 4680 504 3096 6912 4104
720 100 750 150 160 650 70 430 960 570
5400 750 5625 1125 1200 4875 525 3225 7200 4275
1080 150 1125 225 240 975 105 645 1440 855
1152 160 1200 240 256 1040 112 688 1536 912
4680 650 4875 975 1040 4225 455 2795 6240 3705
504 70 525 105 112 455 49 301 672 399
3096 430 3225 645 688 2795 301 1849 4128 2451
6912 960 7200 1440 1536 6240 672 4128 9216 5472
4104 570 4275 855 912 3705 399 2451 5472 3249
解答例:
# 解答例1 # 要素数 n を整数で受け取る n = gets.to_i # 配列 A を受け取る(A -> ary とする) ary = gets.split.map(&:to_i) # 掛け算結果を格納する配列を用意する(n * n の二次元配列) result = Array.new(n) { Array.new(n, nil) } # 二重ループで掛け算を行う n.times do |i| n.times do |j| result[i][j] = ary[i] * ary[j] end end # 掛け算の結果を表示する result.each do |row| puts row.join(" ") end
# [解答例2] # 要素数 n を受け取る n = gets.to_i # 配列 A を受け取る(A -> ary とする) ary = gets.split.map(&:to_i) # 2重ループで要素を掛け算する ary.each do |a| # 1 行分の計算結果を表示する puts ary.each.map { |b| a * b }.join(" ") end
今回のまとめ
- 決められた回数の繰り返しは
times
メソッド、each
メソッドを利用する - 条件を満たすまで繰り返すときは
while
メソッドを利用する - 繰り返し処理の中に繰り返し処理を記述することで多重ループを作ることが出来る
今回紹介した以外にも繰り返しメソッドはありますが、times・each・while を覚えておけば大体対応出来ると思います!