Set

Added in v1.9 · Updated March 13, 2026 · Modules
ruby stdlib set collection

The Set class provides a collection of unordered values with no duplicates. It’s part of Ruby’s standard library and is useful when you need to track unique items or perform set operations.

Overview

A Set is like an Array but automatically ensures all elements are unique:

  • No duplicates: Adding the same element twice has no effect
  • Unordered: Elements have no specific order
  • Fast lookups: Efficient membership testing

Creating a Set

require 'set'

# Create from an array
set = Set.new([1, 2, 3])

# Create empty and add items
set = Set.new
set.add(1)
set.add(2)

# Using the shortcut (Ruby 3.0+)
set = Set[1, 2, 3, 4, 5]

Set.new Parameters

ParameterTypeDefaultDescription
enumEnumerablenilInitial elements
comparatorProcnilCustom comparison block
# With a block for transformation
Set.new([1, 2, 3]) { |x| x * 2 }
# => Set{2, 4, 6}

# With custom comparison
require 'set'
Set.new([1, 2, 3], ->(a, b) { a.abs == b.abs })

Adding and Removing Elements

set = Set.new

# Add single element
set.add(1)
set.add(2)

# Add multiple elements
set.merge([3, 4, 5])

# Remove element
set.delete(2)

# Check if empty
set.empty?  # => false

# Clear all elements
set.clear

Add Methods

MethodDescription
add(element)Add one element
<<Alias for add
add?(element)Add only if not present (returns nil if existed)
merge(enumerable)Add multiple elements
replace(enumerable)Replace all elements
set = Set.new([1, 2, 3])

# add? returns nil if already present
result = set.add?(2)  # => nil (already there)
result = set.add?(4)  # => Set{1, 2, 3, 4}

# << is an alias for add
set << 5

Membership Testing

set = Set.new([1, 2, 3])

set.include?(2)   # => true
set.member?(2)     # => true (alias)
set.include?(99)   # => false

Set Membership Methods

MethodDescription
include?(obj)Check if element exists
member?(obj)Alias for include?
subset?(other)Check if all elements in another set
superset?(other)Check if superset of another set
proper_subset?(other)Check if proper subset
proper_superset?(other)Check if proper superset
set1 = Set[1, 2, 3]
set2 = Set[1, 2, 3, 4]

set1.subset?(set2)      # => true
set2.superset?(set1)    # => true
set1.proper_subset?(set2)  # => true
set1 == Set[1, 2, 3]    # => true

Set Operations

set1 = Set[1, 2, 3, 4]
set2 = Set[3, 4, 5, 6]

# Union (combine)
set1 | set2        # => Set{1, 2, 3, 4, 5, 6}
set1 + set2        # => Set{1, 2, 3, 4, 5, 6}
set1.merge(set2)  # => Set{1, 2, 3, 4, 5, 6}

# Intersection (common)
set1 & set2        # => Set{3, 4}
set1.intersection(set2)  # => Set{3, 4}

# Difference
set1 - set2        # => Set{1, 2}
set1.difference(set2)  # => Set{1, 2}

# Symmetric difference
set1 ^ set2        # => Set{1, 2, 5, 6}

Set Operations Methods

MethodOperatorDescription
union(other)``
intersection(other)&Common elements
difference(other)-Elements in self but not other
^XORElements in either but not both
# Practical example: find unique items
authors = ["alice", "bob", "alice", "carol", "bob"]
unique_authors = Set.new(authors)
# => Set{"alice", "bob", "carol"}

Enumerable Methods

Since Set includes Enumerable, you can use many iteration methods:

set = Set.new([1, 2, 3, 4, 5])

# Map
set.map { |x| x * 2 }  # => [2, 4, 6, 8, 10]

# Select
set.select { |x| x > 2 }  # => Set{3, 4, 5}

# Reject
set.reject { |x| x.even? }  # => Set{1, 3, 5}

# Each
set.each { |x| puts x }

# Count
set.count   # => 5
set.count { |x| x > 3 }  # => 2

Practical Examples

Removing Duplicates

# From an array with duplicates
items = [1, 2, 2, 3, 3, 3, 4]
unique = Set.new(items).to_a
# => [1, 2, 3, 4]

# Or use Array#uniq (built-in)
items.uniq

Tracking Seen Items

def find_duplicates(items)
  seen = Set.new
  duplicates = Set.new
  
  items.each do |item|
    if seen.include?(item)
      duplicates.add(item)
    else
      seen.add(item)
    end
  end
  
  duplicates.to_a
end

find_duplicates([1, 2, 3, 2, 4, 3, 5])
# => [2, 3]

Tag System

class Article
  attr_reader :tags
  
  def initialize
    @tags = Set.new
  end
  
  def add_tag(tag)
    @tags.add(tag.downcase)
  end
  
  def has_tag?(tag)
    @tags.include?(tag.downcase)
  end
end

article = Article.new
article.add_tag("Ruby")
article.add_tag("rails")
article.add_tag("Ruby")  # Duplicate - no effect

article.tags        # => Set{"ruby", "rails"}
article.has_tag?("RUBY")  # => true

User Permissions

class User
  attr_reader :permissions
  
  def initialize
    @permissions = Set.new
  end
  
  def grant(permission)
    @permissions.add(permission)
  end
  
  def revoke(permission)
    @permissions.delete(permission)
  end
  
  def can?(permission)
    @permissions.include?(permission)
  end
end

user = User.new
user.grant(:read)
user.grant(:write)
user.can?(:read)    # => true
user.can?(:delete)  # => false

See Also

  • Array — ordered collections with duplicates allowed
  • Hash — key-value pairs
  • YAML — serialization format