Rubyメモ: 複数の値を同時に代入する(多重代入)

多重代入の基本

Ruby の代入式は、複数の左辺値や右辺値をとることができます。

a, b, c = 100, 200, 300

上記のような代入式を記述すると、次のように個別に代入するのと同様の結果になります。

a = 100
b = 200
c = 300

多重代入によるそれぞれの代入処理は並列に行われるため、次のように変数の値をスワップできます。

a, b = b, a

左辺値の方が多いとき

a, b, c = 100, 200

上記の場合、c の値は nil となります。

右辺値の方が多いとき

a, b = 100, 200, 300

上記の場合、右辺値の 300 は単純に破棄されます。

左辺値の 1 つにプレフィックスとしてアスタリスク * を付けることにより、過剰な右辺値をまとめて配列の形で受け取ることができます。 アスタリスクはどの変数に付けても構いませんが、左辺値のうち 1 つにしか付けられません。

a, *b = 100, 200, 300     # a=100, b=[200,300]
*a, b = 100, 200, 300     # a=[100,200], b=300
*a, *b = 100, 200, 300    # シンタックスエラー

アスタリスクの付いた変数は必ず配列の形になります。 これは、左辺値と右辺値の数が等しい場合や、左辺値の方が多い場合も同様です。 アスタリスクの付いた変数は空配列 [] になることはありますが、nil になることはありません。

a, *b, c = 100, 200, 300  # a=100, b=[200], c=300
a, *b = 100   # a=100, b=[]
*a, b = 100   # a=[], b=100

右辺値に配列を指定した場合

右辺値として配列を 1 つだけ指定した場合は、配列要素が展開されてから代入処理が実行されます。

a, b, c = [100, 200, 300]  # a=100, b=200, c=300

右辺値が 2 つ以上あり、その中に配列が含まれる場合は、配列のまま代入されます。

a, b, c = 100, [200, 300], 400  # a=100, b=[200,300], c=400

右辺値が 2 つ以上ある場合でも、配列のプレフィックスとしてアスタリスク * を付けると、明示的にその配列要素を展開してから代入できます。

a, b, c = 100, *[200, 300], 400  # a=100, b=200, c=300

利用例

例: 配列の特定の位置の要素を受け取る
title, url = site_info[0, 2]
例: 多値関数の戻り値を受け取る
def minmax_indices(arr)
  minIndex = 0
  maxIndex = 0
  arr.each_with_index do |val, i|
    if val < arr[minIndex]
      minIndex = i
    elsif val > arr[maxIndex]
      maxIndex = i
    end
  end
  [minIndex, maxIndex]
end

x, y = minmax_indices([20, 50, 30, 10, 40])  # x=3, y=1