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
| Parameter | Type | Default | Description |
|---|---|---|---|
enum | Enumerable | nil | Initial elements |
comparator | Proc | nil | Custom 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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Operator | Description |
|---|---|---|
union(other) | ` | ` |
intersection(other) | & | Common elements |
difference(other) | - | Elements in self but not other |
^ | XOR | Elements 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