Ruby 2.6+
Ruby's introduced difference
in 2.6.
This gives a very fast, very readable solution here, as follows:
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3, 4, 5, 6]
a.difference(b).any?
# => false
a.difference(b.reverse).any?
# => false
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3]
a.difference(b).any?
# => true
However, the reverse isn't true:
a = [1, 2, 3]
b = [1, 2, 3, 4, 5, 6]
a.difference(b).any?
# => false
This means to get the difference in both directions it is necessary to run:
a.difference(b).any? || b.difference(a).any?
Running the benchmarks:
a = Array.new(1000) { rand(100) }
b = Array.new(1000) { rand(100) }
Benchmark.ips do |x|
x.report('sort') { a.sort == b.sort }
x.report('sort!') { a.sort! == b.sort! }
x.report('to_set') { a.to_set == b.to_set }
x.report('minus') { ((a - b) + (b - a)).empty? }
x.report('difference') { a.difference(b).any? }
x.report('difference two way') { a.difference(b).any? || b.difference(a).any? }
end
sort 10.175k (± 6.2%) i/s - 50.778k in 5.015112s
sort! 10.513k (± 6.8%) i/s - 53.212k in 5.089106s
to_set 4.953k (± 8.8%) i/s - 24.570k in 5.037770s
minus 15.290k (± 6.6%) i/s - 77.520k in 5.096902s
difference 25.481k (± 7.9%) i/s - 126.600k in 5.004916s
difference two way 12.652k (± 8.3%) i/s - 63.232k in 5.038155s
My takeaway would be that difference
is a great choice for a one directional diff.
If you need to check in both directions, it's a balance between performance and readability. For me, the readability pips it, but that's a call to be made on a case by case basis.
Hope that helps someone!