プログラミング的なSomething

プログラミング的なSomething

ITエンジニア(?)目線で生活・自転車・トレーニング話を綴ります

CodeIQに出題されている問題をやってみた その②

再びCodeIQ

CodeIQ に出した「メソッド名を当てる空欄補充問題」の解説・解題

第2問chars_in_allに取り組みます。

split

splitは言わずと知れた文字列分割のメソッドです。 問題内ではhoge.split(//)と書かれていて少し面食らいましたがhoge.split("")と同義(要するに1文字づつ区切るよって意味)なので問題なしです。

sort

昇順なのでhoge.sortでOKです。降順の場合の処理を備忘のため書いておきます。

[3, 4, 1, 6, 9].sort { |a,b| b <=> a }
#=>[9, 6, 4, 3, 1]

ブロック引数a、 bには、比較する2要素が入ります。 ブロックの戻り値が-1ならaが先、0なら同じ、1ならbが先となります。昇順のsortであれば、(各必要ないですが)a<=>bのように書くわけですね。

inject

injectメソッドは問題からはその機能をあまり理解できなかったのでリファレンスを参照しています。

injectはブロックを使って計算するためのメソッドです。順に「要素1、要素2」、「前回の戻り値、要素3」、「前回の戻り値、要素4」、、、といった感じで、繰り返しの計算に使える。

injectは初期値を持たせることができるので、その場合は第1要素とともに評価される。「初期値、要素1」、「戻り値、要素2」、、、という繰り返し処理が走る

numbers = [4, 3, 9, 8, 5, 6, 1, 7, 2]
puts numbers.inject {|sum, n| sum + n } #=>45
puts numbers.inject(100) {|diff, n| diff - n } #=>55

リファレンスの例文を備忘のため載っけておきます。これでなら理解が簡単でした。

リファレンス:inject (Enumerable)

CodeIQの問題中でのinjectの使い方

以下のような使い方をしています。

(strings.map{ |i| i.split(//) }.inject(&:&) || []).uniq.sort

inject(&:&)が単なる記号に見えて仕方ないですが、以下のような解釈とのことです。 - 最初の&は実引数を渡すための記号 - :はシンボルリテラル開始 - 最後の&はシンボルリテラルの内容

正直、小難しい解釈ができなかった。

最初の&は実引数渡す処理ってことで、リファレンスで書かれているような、ブロックの処理を簡便化したものという理解でOKで、後半の:&はブロックを&メソッドでつなげる役割をしていると認識しました。

array = array1{$:method}がarray = array1{|a| a.method }と同義になることをから推察しています。

かくして、ブロックA(実際は配列) & ブロックB(配列) & ブロックC(配列)…という繰り返し処理が走り、重複した文字列を炙り出すことができます。

感想

inject(&:&)の説明に出てくる”to_procする”ということの意味をもう少し自分のなかで落としこむ必要がありそうです。