解答例 ─ Ruby初級者向けレッスン 44回
第56回 Ruby/Rails勉強会@関西 での Ruby初級者向けレッスン 44回 の解答例 *1
演習問題 1
0 から 9 までの数値をもつ配列 a がある。a = (0..9).to_a a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 各要素を順番に表示しよう。
- 各要素を 2倍した値を持つ配列を作ろう。
- 全要素の合計値を計算しよう。
- スライドのおさらい。
- 改めてやってみると、意外とできないかも知れないよ。
# -*- coding: utf-8; -*- # 0 から 9 までの数値をもつ配列 a がある。 a = (0..9).to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 各要素を順番に表示しよう a.each{|i| puts i} # >> 0 # >> 1 # >> 2 # >> 3 # >> 4 # >> 5 # >> 6 # >> 7 # >> 8 # >> 9 # 各要素を 2倍した値を持つ配列を作ろう a.map{|i| i * 2} # => [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] # 全要素の合計値を計算しよう a.inject{|s, i| s + i} # => 45 ## マニアが書くと a.inject(:+) # => 45
演習問題 2
0 から 9 までの数値をもつ配列 a がある。
- 奇数の要素だけを持つ配列を作ろう。
- ただし odd? メソッドは使用禁止。
- パズルだと思って、いろいろやってみよう。
# -*- coding: utf-8; -*- # 0 から 9 までの数値をもつ配列 a がある。 a = (0..9).to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 奇数の要素だけを持つ配列を作ろう a.select{|i| i.odd?} # => [1, 3, 5, 7, 9] # ただし odd? メソッドは使用禁止 # 2 で割った余りが 1 なら奇数 a.select{|i| i % 2 == 1} # => [1, 3, 5, 7, 9] # 偶数でなければ、それは奇数 a.select{|i| !i.even?} # => [1, 3, 5, 7, 9] # rubyist は true/false の否定を嫌う # reject は式が真の要素を捨て去る a.reject{|i| i.even?} # => [1, 3, 5, 7, 9] ## マニアが書くと a.reject(&:even?) # => [1, 3, 5, 7, 9]
マニアのコードに出てきた & は、スライドに登場した、ブロックの受け渡しに使う & とは少し違う。*2
演習問題 3
Enumerable#map を自作してみよう。module Enumerable def my_map …… end endただしEnumerable#map とEnumerable#map! は使用禁止。
会場には「mapが使えないなら collectを使えばいいじゃない」と言う人がいた。
こういうことですね。わかります。*3
module Enumerable def my_map &block collect(&block) end end a = [*0..4] # => [0, 1, 2, 3, 4] a.map{|i| i * 2} # => [0, 2, 4, 6, 8] a.my_map{|i| i * 2} # => [0, 2, 4, 6, 8] a.map # => #<Enumerator: [0, 1, 2, 3, 4]:map> a.my_map # => #<Enumerator: [0, 1, 2, 3, 4]:collect>
惜しい。
多くのブロック付きメソッドはブロックを渡さないと Enumerator を返す。
my_map の方は #
# -*- coding: utf-8; -*- # Enumerable#map を自作してみよう # ただし Enumerable#map と Enumerable#map! は使用禁止 module Enumerable def my_map unless block_given? # ブロックがもらえなかったら Enumerator を返す to_enum __callee__ else # 空の Array を用意し、 inject([]) do |result, item| # ブロックの評価結果を追加する result << yield(item) end end end end # 試してみる a = [*0..3] # => [0, 1, 2, 3] # map と my_map の比較 a.map{|i| i * 2} # => [0, 2, 4, 6] a.my_map{|i| i * 2} # => [0, 2, 4, 6] # Enumerator も比較 i = a.map # => #<Enumerator: [0, 1, 2, 3]:map> j = a.my_map # => #<Enumerator: [0, 1, 2, 3]:my_map> i.next # => 0 i.next # => 1 i.next # => 2 i.next # => 3 j.next # => 0 j.next # => 1 j.next # => 2 j.next # => 3 j.next # => # ~> -:40:in `next': iteration reached an end (StopIteration) # ~> from -:40:in `<main>'
詳しくは、時間がとれたら書きたい。*4