多重代入
多重代入とは、複数の値を同時に代入することです。
a, b = 1, 2 puts a #=> 1 puts b #=> 2
多重代入は配列にも使える
特に便利なのが、配列の要素を一度に代入できるところです。
a, b, c = [1, 2, 3] puts a #=> 1 puts b #=> 2 puts c #=> 3
たとえば、以前紹介した次のコード。
入力値はapple banana orange
。値は文字列でスペース区切り、最後に改行を含む。
input = gets.split puts "私は、#{input[0]}と#{input[1]}と#{input[2]}が好きです。" #=> 私は、appleとbananaとorangeが好きです。
多重代入を利用すると、次のように書くことができます。
a, b, c = gets.split puts "私は、#{a}と#{b}と#{c}が好きです。" #=> 私は、appleとbananaとorangeが好きです。
見やすくなりました!
最初何が起きているのかよくわからなかったので、順を追って説明してみます。
#"apple banana orange"を受け取って変数inputに代入 input = gets #"apple banana orange"を["apple", "banana", "orange"]という配列にして変数fruitsに代入 fruits = input.split #a, b, c = fruitsは、ここではa, b, c = ["apple", "banana", "orange"]に同じ a, b, c = fruits #確認のため変数a, b, cの中身を表示してみる puts a #=> apple puts b #=> banana puts c #=> orange puts "私は、#{a}と#{b}と#{c}が好きです。" #=> 私は、appleとbananaとorangeが好きです。
各要素を数値に変換する
受け取る値を数値として使いたいときはどうしたらよいでしょうか。
(例題)n, m
2つの整数が標準入力で渡される。n
とm
の積を出力せよ。入力値は文字列でスペース区切り、最後に改行を含むものとする。
入力値は2 3
とします。
n, m = gets.split
puts n * m #=> エラー!
n, m = gets.split
は、gets
で受け取った文字列をsplit
によってスペースで分割して配列にした上で、nとmにそれぞれ代入(多重代入)しています。なぜエラーが起きたのでしょうか。p
メソッドを使ってnとmの中身を確認してみます。
n, m = gets.split p n #=> "2" p m #=> "3"
nに2、mに3が代入できていますが、数値ではなく文字列のままなので、"2" * "3"
つまり文字列同士の掛け算ができずエラーになったことがわかります。整数に変換するto_i
メソッドを使えばいいと思いますが、n.to_i
、m.to_i
と一つひとつ書く方法だと、入力値が多い場合に大変です。こんなとき使えるメソッドがあったような…
map
メソッドで配列の各要素を変換
map
は、配列の各要素を処理し、変換後の新しい配列を返すメソッドです。
p [1, 2, 3].map(&:to_s) #=> ["1", "2", "3"]
上のコードでは、[1, 2, 3]という配列の各数値を、一つずつto_s
メソッドで処理し文字列に変換しています。
ちなみにmap
を使わず配列に直接to_s
を使うと、配列全体を文字列に変換してしまいます。
p [1, 2, 3].to_s #=> "[1, 2, 3]"
話がそれましたが、map
を使って例題をやっていきます。
いきなり多重代入もmap
も全部やると初心者の自分は訳がわからなくなるので、一つずつ処理しながら、適宜変数の中身を確認できるp
メソッドを挟みます。
#受け取った文字列をinputという変数に代入 input = gets p input #=> "2 3\n" #splitで"2 3\n"をスペースで分割して配列に入れると同時に末尾の改行"\n"を削除して変数aryに代入 ary = input.split p ary #=> ["2", "3"] #mapメソッドでaryの各要素である文字列を整数に変換し、新しい配列を変数intsに代入 ints = ary.map(&:to_i) p ints #=> [2, 3] #多重代入。ここでは n, m = [2, 3]に同じ n, m = ints p n #=> 2 p m #=> 3 #計算して結果を出力 puts n * m #=> 6 #nもmも整数なのでエラーにならず計算できる
頭の整理ができたところで、まとめて書くと次のようになります。
n, m = gets.split.map(&:to_i) puts n * m #=> 6
代入時にchomp
を入れる例が多いですが、不要な理由については以下の記事をご覧ください。