Basic Object

Deep thoughts on web programming

Sets and Set Operators in Ruby

Though they’re rarely used, Ruby supports sets - unordered collections of unique objects. The Set class isn’t required by default, so you’ll have to require 'set', and the constructor is a little verbose compared to that of an array or a hash1, but sometimes they’re just what you need.

They have a couple of big advantages over Ruby’s arrays and hashes:

  1. A set only contains unique elements, which makes uniqueness checks unnecessary. Adding an element to a set that is already a member of that set will fail silently.

  2. While looking up an element by index is not possible (as it is with Array), looking up an element is faster than in an array2. This is, as the Ruby documentation says, because “Set uses Hash as storage.”

In addition, the Set class introduces some interesting methods (including #disjoint?, #intersect?, #classify, and #divide) and operators. Perhaps the most useful of these are & (the intersection operator), | (the union operator), - (the difference operator), and ^ (the exclusion operator). All but the last of these can also be used with arrays in Ruby.

Some examples:

1
2
3
4
Set[1, 2, 3, 4] & Set[3, 4, 5, 6] # => #<Set: {3, 4}>
Set[1, 2, 3, 4] | Set[3, 4, 5, 6] # => #<Set: {1, 2, 3, 4, 5, 6}>
Set[1, 2, 3, 4] ^ Set[3, 4, 5, 6] # => #<Set: {5, 6, 1, 2}>
Set[1, 2, 3, 4] - Set[3, 4, 5, 6] # => #<Set: {1, 2}>
  1. You have to use the explicit constructor (Set.new [1, 2, 3, 4] or Set[1, 2, 3, 4]). You can also turn an array into a set with the #to_set method.

  2. This is because arrays are really best at index lookups. ArrayFields is an interesting Ruby library that appears to combine the best of hashes and arrays, adding fast keyword lookup using the same syntax as hashes.