やりたいこと
各要素がStringで与えられたArrayを適切な型に変換したい
['1', '2', '3'] -> [1, 2 ,3] # 整数
['1', '2', '3'] -> [1.0, 2.0 ,3.0] # 実数
...
解決策
step 1
['1', '2', '3'].map(&:to_i)
などが思いつく。
では、これを'float', 'integer'などの引数でコントロールできないかと考えた。
def convert(data_type)
case data_type
when 'integer'
:to_i
when 'float'
:to_f
else
:itself
end
end
このように定義しておけば、
['1', '2', '3'].map(&convert('integer'))
>> [1, 2, 3]
['1', '2', '3'].map(&convert('float'))
>> [1.0, 2.0, 3.0]
できた!
step 2
しかし、上の処理の場合、nilの入ったArrayだと以下のようにnil
が0に変換されてしまう。
['1', '2', nil].map(&convert('integer'))
>> [1, 2, 0]
['1', '2', nil].map(&convert('float'))
>> [1.0, 2.0, 0]
次の目的:nil以外のときに、変換をしたい!!
そこで軽くProcについて調べると、:to_i
はto_proc
でProc
に変換することができるので、上の関数に以下を加えることで、nilのときは、何もせず、nil以外のときに、proc.call(x)
を呼ぶ=変換する関数になる
proc = convert('integer').to_proc
-> (x) { proc.call(x) unless x.nil? }
全て
def convert(data_type)
symbol = case data_type
when 'integer'
:to_i
when 'float'
:to_f
when 'date'
:to_date
when 'datetime'
:to_datetime
else
:itself
end
proc = symbol.to_proc
-> (x) { proc.call(x) unless x.nil? }
end
これで、['1', '2' , nil].map(&convert('float'))
が[1.0, 2.0, nil]
を返すようになった!