11/08/2018, 23:59

Array.| メソッドを使いたく無い

Array.| メソッド Array の | メソッドは与えられた引数であるArrayとの和集合を求めるために使います。 [ 1 , 2 , 3 ] | [ 2 , 3 , 4 ] = > [ 1 , 2 , 3 , 4 ] ですが、この|というのは、コードの中に入ると中々読みづらく、ブロック等の仮引数と見間違えることもしばしば・・・ そこで、このメソッドを使わない理由を考えました。 読みづらい これは前述の通りです。 遅い これが実証できれば、大手を振って利用を止められます。 ...

Array.| メソッド

Array の | メソッドは与えられた引数であるArrayとの和集合を求めるために使います。

[1, 2, 3] | [2, 3, 4]
=> [1, 2, 3, 4]

ですが、この|というのは、コードの中に入ると中々読みづらく、ブロック等の仮引数と見間違えることもしばしば・・・

そこで、このメソッドを使わない理由を考えました。

読みづらい

これは前述の通りです。

遅い

これが実証できれば、大手を振って利用を止められます。 簡単なベンチマークを取ってみました。

代替処理

和集合ということは、2つのArrayを加えて、重複を弾けばOKです。 それをそのままRubyのコードに置き換えると、

([1, 2, 3] + [2, 3, 4]).uniq
=> [1, 2, 3, 4]

こういうことです。2つに限ったことではありません。複数個で試してみると、

[1, 2, 3] | [2, 3, 4] | [3, 4, 5] | [4, 5, 6]
=> [1, 2, 3, 4, 5, 6]

([1, 2, 3] + [2, 3, 4] + [3, 4, 5] + [4, 5, 6]).uniq
=> [1, 2, 3, 4, 5, 6]

間違い無いですね。

2個のArrayでの比較

それぞれにBenchmarkを取ってみます。まずは2対のArrayの和集合。

Benchmark.measure do
  1000000.times do
    [1, 2, 3] | [2, 3, 4]
  end
end
=> #<Benchmark::Tms:0x007fe500ba98d8
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=1.924258,
 @stime=0.010000000000000009,
 @total=1.9000000000000006,
 @utime=1.8900000000000006>

Benchmark.measure do
  1000000.times do
    ([1, 2, 3] + [2, 3, 4]).uniq
  end
end
=> #<Benchmark::Tms:0x007fe50279a7b8
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=2.730523,
 @stime=0.030000000000000027,
 @total=2.55,
 @utime=2.5199999999999996>

うーん、ちょっと遅いですね。 この場合は、1.5倍位遅いのと可読性が高い(と個人的に思っている)のとを天秤に掛けて考える感じでしょう。

4個のArrayでの比較

次に4つのArrayの和集合を確認してみます。

Benchmark.measure do
  1000000.times do
    [1, 2, 3] | [2, 3, 4] | [3, 4, 5] | [4, 5, 6]
  end
end
=> #<Benchmark::Tms:0x007fe505000158
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=5.570456,
 @stime=0.010000000000000009,
 @total=5.57,
 @utime=5.5600000000000005>

Benchmark.measure do
  1000000.times do
    ([1, 2, 3] + [2, 3, 4] + [3, 4, 5] + [4, 5, 6]).uniq
  end
end
=> #<Benchmark::Tms:0x007fe5014d5cb8
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=4.201799,
 @stime=0.010000000000000009,
 @total=4.190000000000001,
 @utime=4.1800000000000015>

今度は逆転しました。|演算子では、演算の度に重複を弾いているので、纏めて重複を弾く後者の処理の方が早くなったと思われます。

結論

処理速度の面では、少数のArrayの連結では|メソッド、多数では+メソッドとuniqメソッドの併用が有利です。

ただ、そこまで大きな差は無いので、可読性等を考慮して利用を決めて良さそうです。

掲題の通り、私は|メソッドが読みづらいと感じているので、+メソッドとuniqメソッドの併用で統一しようと思います。

0