RubyでAtCoderを解いていて、なんとなく雰囲気で使っていたメソッドを調べた。
map
こんな感じで使っていた
1 2 3 4 5
こんな感じの標準入力を受け取る際に、
array = gets.chomp.split(" ").map(&:to_i)
p array # => [1, 2, 3, 4, 5]
として、配列に文字列ではなく、数値として格納する際に利用していた。
ここでのmapの役割
配列の各要素に対して、ブロックを評価した結果を全て含む配列を返す。Rubyのリファレンスマニュアルの利用例を以下に紹介
# すべて 3 倍にする
p [1, 2, 3].map {|n| n * 3 } # => [3, 6, 9]
なるほど。
map(&:to_i)の"&:"って何?
mapでやっていることは、リファレンスマニュアルの例で理解できた。じゃあ、&は何者なのか?
&
今回のケースでは以下のような役割があるらしい。
Proc オブジェクトをブロックとして使う
Procとは
ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです。
ちょっとよくわからないけど、ブロック付きのメソッドに対して、&を使ってProcオブジェクトを呼び出すと、いい感じに書けるらしい。
つまり、初めに戻って、
array = gets.chomp.split(" ").map(&:to_i)
と
array = gets.chomp.split(" ").map { |number| number.to_i }
の振る舞いは同じで、前者の方が直感的でわかりやすい気がする。
inject
こんな感じで使っていた
[1,2,3,4,5]
こんな感じの配列の和を計算するときに、
array.inject(:+) # => 15
ここでのinjectの役割
ブロックを使って繰り返し計算を行うのに使う。injectメソッドにブロックの代わりにシンボルsymでメソッド名を渡すことができる。
第1引数initに初期値を指定すると、「初期値.メソッド(要素1)」、「前回の結果.メソッド(要素2)」、...を計算する。
リファレンスの例を紹介
numbers = [4, 3, 9, 8, 5, 6, 1, 7, 2]
puts numbers.inject(:+) # => 45
puts numbers.inject(100, :-) #=> 55
まとめ
知らないことが多くて楽しい。競技プログラミングをちびちび頑張る。