rubyguides

Array#uniq

The .uniq method removes duplicate elements from an array, keeping only the first occurrence of each unique value. The .uniq! variant modifies the array in place.

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

# uniq! modifies in place
arr = [1, 1, 2, 2, 3]
arr.uniq!
arr  # => [1, 2, 3]

Syntax

array.uniq
array.uniq { |element| block }

array.uniq!
array.uniq! { |element| block }

Parameters

ParameterTypeDefaultDescription
blockBlockOptionalIf provided, determines uniqueness based on the block’s return value

What .uniq Returns

.uniq returns a new array containing unique elements. The original array remains unchanged.

original = [1, 2, 2, 3, 3, 3]
unique = original.uniq

original  # => [1, 2, 2, 3, 3, 3] (unchanged)
unique    # => [1, 2, 3] (new array)

.uniq! returns self if duplicates were removed, or nil if the array already had no duplicates:

arr = [1, 2, 3]
result = arr.uniq!
# => nil (no changes made)

arr = [1, 1, 2]
result = arr.uniq!
# => [1, 2] (returns self)

Using a Block

Pass a block to determine uniqueness based on a computed value:

# Get unique lengths
words = ["cat", "dog", "horse", "mouse", "cow"]
words.uniq { |word| word.length }
# => ["cat", "horse", "mouse"]

# First "cat" (len 3), then "horse" (len 5), then "mouse" (len 5 - duplicate!)
# Result: ["cat", "horse", "mouse"]

This is useful when you want uniqueness based on a specific attribute rather than the element itself.

Common Use Cases

Removing Duplicates from User Input

# Form submissions often have duplicate values
emails = ["user@example.com", "admin@example.com", "user@example.com"]
emails.uniq
# => ["user@example.com", "admin@example.com"]

Processing Database Results

# Database queries might return duplicate records
user_ids = [1, 2, 1, 3, 2, 1]
user_ids.uniq
# => [1, 2, 3]

With Chaining

# Chain with other methods
[1, 1, 2, 2, 3, 3].select(&:odd?).uniq
# => [1, 3]

# Get unique values and sort
[3, 1, 2, 3, 1, 2].uniq.sort
# => [1, 2, 3]

Gotchas

Understanding First Occurrence Retention

.uniq always keeps the first occurrence, regardless of position:

# The second "cat" is removed, even though duplicates exist elsewhere
["cat", "dog", "cat", "bird", "cat"].uniq
# => ["cat", "dog", "bird"]

Block Returns nil

If the block returns nil, elements are compared by their nil status:

[1, 2, nil, nil, 3].uniq { |n| n&.even? }
# => [1, nil, 3]
# 1 -> even? returns false
# 2 -> even? returns true (kept)
# nil -> even? returns nil (different from false, kept)
# nil -> even? returns nil (same as previous nil, removed)
# 3 -> even? returns false (different from true, kept)

Hash Keys and uniq

Ruby hashes don’t allow duplicate keys, so converting through a hash can also remove duplicates (though order may vary in older Ruby):

# Alternative approach for uniqueness
[1, 2, 1, 3, 2].each_with_object({}) { |n, h| h[n] = true }.keys
# => [1, 2, 3]

# But prefer uniq for clarity and guaranteed order

See Also

  • .compact — Remove nil values from arrays
  • .filter — Select elements matching a condition
  • .flatten — Flatten nested arrays