最近、Ruby Silverの資格試験の勉強をしています。全然Rubyのこと理解してないんだなぁと絶望しつつも伸びしろを感じております😚
以下の問題を考えていた際に、配列に対する | と || の違いが気になったので調べてみました。
問題:
XXXXに記述することで、実行結果が30以上になるプログラムを選択してください。
a = [-1, 2, 3, 4, 5]
b = (4..6).to_a
puts XXXX
選択肢:
a.inject(:+) + b.inject(:+)(a | b).inject(:-).abs + (a & b).inject(:+).abs(a | b).inject(:*) + b.inject(0) { |x, y| x + y ** 3 }((a || b).map(&:succ).inject(:*) * (a && b).inject(:*).abs2 + 29)
この問題のa | b と a || b の結果がどうなるか分からなかったので、調べてみました。a || bを配列で使うイメージがない…
a | b の挙動
| 演算子は、配列同士の和集合です。
両方の配列に含まれる要素を、重複なく結合した新しい配列を返します。
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]
result = a | b
puts result.inspect # => [-1, 2, 3, 4, 5, 6]
この例では、a と b の和集合が作成され、重複する要素 4, 5 は一度だけ含まれる結果になります。
整数オブジェクトに対しては、ビット単位のOR演算を行います。(どっちか1なら1)
puts 8 | 5 # => 13 (1000 | 0101 ⇒ 1101)
a & b の挙動
& 演算子は、配列同士の積集合です。
両方の配列に共通して含まれる要素だけを持つ新しい配列を返します。
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]
result = a & b
puts result.inspect # => [4, 5]
この例では、a と b に共通する要素 4 と 5 が結果として返されます。
整数オブジェクトに対しては、ビット単位のAND演算を行います。(どっちも1なら1)
puts 12 & 5 # => 4 (1100 | 0101 ⇒ 0100)
a || b の挙動
|| 演算子は、左項 a が「真」と評価される場合には a を返し、そうでない場合には右項 b を返します。Rubyでは、nil と false 以外のすべての値が「真」として扱われます。
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]
result = a || b
puts result.inspect # => [-1, 2, 3, 4, 5]
この場合、a が配列で「真」と評価されるため、result には a が返され、b は評価されません。
a が nil の場合
a = nil
b = [4, 5, 6]
result = a || b
puts result.inspect # => [4, 5, 6]
a が nil で「偽」と評価されるため、result には b が返されます。
変数がnilの時に初期値を設定する方法でよく見かけますね。
a && b の挙動
&& 演算子は、左項 a が「偽」と評価される場合には a を返し、そうでなければ右項 b を返します。
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]
result = a && b
puts result.inspect # => [4, 5, 6]
a が「真」と評価されるため、result には b が返されます。
a が nil の場合
a = nil
b = [4, 5, 6]
result = a && b
puts result.inspect # => nil
a が「偽」と評価されるため、result には a の値 nil が返されます。
短絡評価の違い
|| と && は短絡評価(ショートサーキット) を行いますが、| と & は短絡評価を行いません。つまり、| と & では、両方のオペランドが必ず評価されます。
例: 短絡評価の違い
a = true
b = false
# 短絡評価あり (||)
result = a || (b = true)
puts b # => false (b は評価されない)
# 短絡評価なし (|)
result = a | (b = true)
puts b # => true (b は評価される)
|| 演算子では、a が true なので、b = true は評価されず、b の値は変わりません。
| 演算子では短絡評価が行われず、b = true が実行されて b は true に変わります。
まとめ
-
||と&&は、論理演算子として条件分岐やデフォルト値の設定に使う。真偽値、配列、数字などに対して動作する。 -
|と&は、配列に対して集合演算を行い、和集合や積集合を返す。整数に対してはビット演算を行う。