全然網羅できてないけどブロック操作系まとめ。
スコープを作ってコレクションを操作できるのはそうだとして、
ブロック内の評価値をまとめたものがブロックの評価結果となるところがポイント。
コードがぐっと短くなって気分が良い。
基本的なeach
最も基本的な配列、ハッシュのeach。配列、ハッシュをレシーバとしてeachメソッドを呼び出す。
評価結果はレシーバ自身。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
arrays = [100, 200, 300] rets = arrays.each do |value| p value end # 100 # 200 # 300 # [100, 200, 300] p rets # [100, 200, 300] hashes = {a1:"a1", a2:"a2", a3:"a3"} rets = hashed.each do |value| p value end # [a1:"a1", a2:"a2", a3:"a3"] # {a1: "a2"} # {a2: "a2"} # {a3: "a3"} # [a1:"a1", a2:"a2", a3:"a3"} p rets # [a1:"a1", a2:"a2", a3:"a3"} |
each_with_index
配列の順序数を付けることができる。
1 2 3 4 5 6 7 8 |
arrays = [100, 200, 300] arrays.each_with_index do |value,index| p "#{index}_#{value}" end # "0_100" # "1_200" # "2_300" # [100, 200, 300] |
each_key, each_value
ハッシュのキーのみ、値のみをブロックで使う場合は以下。
キー、値の両方を使える制限無しの状態でどちらかを使う、というのではなく、
初めからキー、値のどちらを使うかを宣言して、それだけを使うという拘りビリティ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
hashes = {a1:"a1", a2:"a2", a3:"a3"} rets = hashes.each_key do |key| p key end # :a1 # :a2 # :a3 # {:a1=>"a1", :a2=>"a2", :a3=>"a3"} rets2 = hashes.each_value do |value| p value end # "a1" # "a2" # "a3" # {:a1=>"a1", :a2=>"a2", :a3=>"a3"} |
upto, downto
ループを回して、制御変数をインクリメント、デクリメントするケースには専用の構文を使う。
Rubyにはインクリメント演算子は無いし、腐ってもforの外で用意した変数に対して+1を自己代入したりしない。
何より、英語の構文と同じところが気持ちが良い。
1 2 3 4 5 6 7 8 |
100.upto(103) do |i| p i end # 100,101,102,103 103.downto(100) do |j| p j end # 103,102,101,100 |
times
n回の構文,times。
1 2 3 4 |
3.times do |i| p i end # 0,1,2 |
map
mapは、レシーバの各要素分繰り返す。ブロックの評価値は各要素に対応する値となり、新たな配列が返る。
eachだと、評価結果がレシーバ自身であるためレシーバを加工して返す用途に使えないが、
mapを使うと、ブロックの応答として加工済みの配列を返せるので、制御構文がグッと短くなって気持ちが良い。
あくまでもレシーバの個数繰り返すので、ブロックでnilを返すと、評価結果の該当要素がnilになる。
1 2 3 4 5 6 7 |
arrays = [1, 2, 3] rets = arrays.map do |i| "values_#{i}" end ["values_1", "values_2", "values_3"] rets2 = arrays.map do |i| "values_#{i}" if i <3 end ["values_1", "values_2", nil] |
ただ、順序数付きのmap_with_indexはこのような動きをしない。
1 2 3 4 5 |
arrays = [1, 2, 3] rets = arrays.map_with_index do |index,value| "#{index}_#{value}" end p rets # {評価結果なし} |
select
前述の通り、mapはレシーバの個数分繰り返すため、ブロック内の最終評価値がnilとなった場合、
評価値の該当要素がnilになる。
そうではなく、nilでない評価結果をまとめて返したい場合はselectを使う。
1 2 3 |
rets3 = arrays.select do |i| "values_#{i}" if i <3 end ["values_1", "values_2"] |
まだまだ全然網羅できてないけど、とりあえず終了。