Enumerable#uniq

Returns: Array · Updated March 31, 2026 · Enumerable
ruby enumerable uniq deduplicate stdlib

The uniq method returns a new array containing only the unique elements from a collection. Duplicates are removed based on equality (==), and the original order of elements is preserved — the first occurrence of each element is kept.

Basic Usage

Remove duplicates from an array of numbers:

numbers = [1, 2, 2, 3, 1, 4, 3, 5]
numbers.uniq
# => [1, 2, 3, 4, 5]

The returned array contains one occurrence of each unique value, in the order they first appeared.

With strings:

languages = ["ruby", "python", "ruby", "go", "python", "rust"]
languages.uniq
# => ["ruby", "python", "go", "rust"]

With a Block

Pass a block to determine uniqueness based on the block’s return value instead of the elements themselves:

words = ["apple", "apricot", "banana", "blueberry", "cherry"]
words.uniq { |word| word[0] }
# => ["apple", "banana", "cherry"]

The block evaluates word[0] for each element — "apple"[0] and "apricot"[0] both return "a", so only the first "a"-word survives. This is useful when you want uniqueness based on a specific attribute.

Practical Block Example: Unique by Attribute

Given a collection of objects, get one record per category:

products = [
  { name: "Laptop", category: "electronics" },
  { name: "Mouse", category: "electronics" },
  { name: "Carrot", category: "food" },
  { name: "Apple", category: "food" },
  { name: "Desk", category: "furniture" }
]

products.uniq { |p| p[:category] }
# => [{:name=>"Laptop", :category=>"electronics"},
#     {:name=>"Carrot", :category=>"food"},
#     {:name=>"Desk", :category=>"furniture"}]

Order Preservation

uniq preserves the original order of elements. The first occurrence of each unique element is kept:

[3, 1, 4, 1, 5, 9, 2, 6].uniq
# => [3, 1, 4, 5, 9, 2, 6]

This matters when order matters to your application — unlike some deduplication approaches that sort or randomize results.

Difference from & (Set Intersection)

Ruby has two ways to find unique or common elements. uniq removes duplicates from a single array, while & finds the intersection of two arrays:

a = [1, 2, 2, 3, 4]
b = [2, 3, 3, 5]

# uniq removes duplicates from ONE array
a.uniq
# => [1, 2, 3, 4]

# & finds elements present in BOTH arrays
a & b
# => [2, 3]

& requires two arrays and returns elements that exist in both. uniq operates on a single array and removes repeated elements.

When to Use Each

  • Use uniq when you want to deduplicate a single list
  • Use & when you want to find common elements between two lists
# Deduplicate one list
["cat", "dog", "cat", "mouse"].uniq
# => ["cat", "dog", "mouse"]

# Find overlapping tags
user_tags = ["ruby", "rails", "postgres", "linux"]
post_tags = ["ruby", "python", "linux", "docker"]
user_tags & post_tags
# => ["ruby", "linux"]

Handling nil Values

nil is treated as a regular value and participates in uniqueness checking:

[1, nil, 2, nil, 3, nil].uniq
# => [1, nil, 2, 3]

One nil is kept along with one occurrence of each non-nil unique value.

With a block, nil block results work the same way:

data = [1, 2, 3, 4, 5]
data.uniq { |n| n.even? ? "even" : nil }
# => [1, 2]

The block returns nil for odd numbers. Since all odd numbers produce the same block result (nil), only the first odd number survives.

Uniq on Hashes

When called on a hash, uniq first converts the hash to an array of [key, value] pairs:

stock = { apples: 50, bananas: 30, oranges: 25, apples: 20 }
stock.uniq
# => [[:apples, 50], [:bananas, 30], [:oranges, 25], [:apples, 20]]

Note that Ruby’s hash literal syntax actually prevents duplicate keys — the last value for :apples (20) overwrites the first (50). But when working with arrays of pairs or enumerators over hashes, uniq is useful:

# Often used with to_a or to_enum
stock.to_a.uniq
# => [[:apples, 50], [:bananas, 30], [:oranges, 25], [:apples, 20]]

# Using to_enum explicitly
stock.to_enum.uniq
# => [[:apples, 50], [:bananas, 30], [:oranges, 25], [:apples, 20]]

Practical Examples

Removing Duplicate Names

attendees = ["Alice", "Bob", "Charlie", "Alice", "Diana", "Bob"]
attendees.uniq
# => ["Alice", "Bob", "Charlie", "Diana"]

Finding Unique Values by Attribute

users = [
  { name: "Alice", role: "admin" },
  { name: "Bob", role: "member" },
  { name: "Charlie", role: "admin" },
  { name: "Diana", role: "member" }
]

users.uniq { |u| u[:role] }
# => [{:name=>"Alice", :role=>"admin"},
#     {:name=>"Bob", :role=>"member"}]

Counting Occurrences After uniq

Combine uniq with other methods to analyze data:

urls = [
  "https://example.com/page1",
  "https://example.com/page2",
  "https://example.com/page1",
  "https://example.com/page3",
  "https://example.com/page2"
]

# How many unique pages were accessed?
urls.uniq.count
# => 3

# List the unique pages
urls.uniq
# => ["https://example.com/page1",
#     "https://example.com/page2",
#     "https://example.com/page3"]

Chaining with Other Enumerable Methods

scores = [100, 85, 100, 92, 85, 78, 100]

# Get unique passing scores, sorted
scores.select { |s| s >= 80 }.uniq.sort
# => [100, 85, 92, 78] → wait, let's trace this

scores.select { |s| s >= 80 }
# => [100, 85, 100, 92, 85, 100]

scores.select { |s| s >= 80 }.uniq
# => [100, 85, 92]

scores.select { |s| s >= 80 }.uniq.sort
# => [85, 92, 100]

Performance Notes

uniq iterates through the collection once and uses a hash internally to track seen elements. This gives it O(n) time complexity, where n is the collection size.

  • Best for: collections with many duplicates, or when you need block-based uniqueness
  • Alternative for small collections: if you only have two arrays and want common elements, & is more explicit
  • Does not modify the original: uniq returns a new array and leaves the original unchanged
original = [1, 2, 2, 3]
deduped = original.uniq

original
# => [1, 2, 2, 3]

deduped
# => [1, 2, 3]

Return Value

uniq always returns an array, even when called on an enumerable with no duplicates:

[].uniq
# => []

[42].uniq
# => [42]

When given a block, the return type is still an array containing the original elements (not the block results):

[1, 2, 3].uniq { |n| n.even? }
# => [1, 2]

The block only determines uniqueness — the original elements are returned.

See Also