Question
I have a Ruby array that contains duplicate elements:
copy_array = [1, 2, 2, 1, 4, 4, 5, 6, 7, 8, 5, 6]
How can I remove the duplicate values from this array while keeping only unique elements, without writing explicit for loops or manual iteration?
Short Answer
By the end of this page, you will understand how Ruby removes duplicates from arrays using built-in methods such as uniq and uniq!. You will also learn when to use the non-destructive versus destructive version, what order Ruby keeps, and how this pattern is used in real code.
Concept
In Ruby, arrays often contain repeated values. Removing duplicates is a common task called deduplication.
Ruby provides built-in methods so you do not need to write your own loop for this. The most common method is:
array.uniq
This returns a new array containing each value only once.
For example:
[1, 2, 2, 1, 4].uniq
# => [1, 2, 4]
Ruby keeps the first occurrence of each value and removes later repeats.
This matters because deduplication appears often in real programs:
- cleaning user input
- removing repeated IDs from database results
- processing tags or categories
- preparing data before counting or grouping
- avoiding duplicate work in scripts or APIs
Ruby's built-in methods are preferred because they are short, readable, and optimized compared with manually writing loops.
Mental Model
Think of uniq like a guest list at an event.
- The first time a person's name appears, they are added to the list.
- If the same name appears again later, it is ignored.
- The final list contains each guest only once, in the order they first appeared.
So this:
[1, 2, 2, 1, 4, 4]
becomes:
[1, 2, 4]
because Ruby keeps the first 1, first 2, and first 4, then skips the repeats.
Syntax and Examples
The main Ruby methods for removing duplicates from arrays are:
array.uniq # returns a new deduplicated array
array.uniq! # modifies the original array in place
Basic example
copy_array = [1, 2, 2, 1, 4, 4, 5, 6, 7, 8, 5, 6]
unique_values = copy_array.uniq
puts unique_values.inspect
# => [1, 2, 4, 5, 6, 7, 8]
copy_array stays unchanged because uniq returns a new array.
In-place example
copy_array = [1, 2, 2, 1, 4, 4, 5, 6, 7, 8, 5, 6]
copy_array.uniq!
puts copy_array.inspect
# => [1, 2, 4, 5, 6, 7, 8]
Here, the original array is modified.
Step by Step Execution
Consider this code:
copy_array = [1, 2, 2, 1, 4, 4, 5]
result = copy_array.uniq
Step by step, Ruby effectively builds the result like this:
- Start with an empty result.
- Read
1-> not seen before, keep it.- result:
[1]
- result:
- Read
2-> not seen before, keep it.- result:
[1, 2]
- result:
- Read
2again -> already seen, skip it.- result:
[1, 2]
- result:
- Read
1again -> already seen, skip it.- result:
[1, 2]
- result:
- Read
4-> not seen before, keep it.- result:
[1, 2, 4]
- result:
- Read
4again -> already seen, skip it.
Real World Use Cases
Removing duplicates from arrays is useful in many practical situations.
Cleaning form or API input
A user might submit repeated values:
tags = ["ruby", "api", "ruby", "backend"]
clean_tags = tags.uniq
# => ["ruby", "api", "backend"]
Preventing duplicate database IDs
user_ids = [12, 15, 12, 18, 15]
unique_user_ids = user_ids.uniq
# => [12, 15, 18]
Avoiding repeated work
If a job queue or script gets duplicate items, deduplication helps avoid processing the same item twice.
file_paths = ["a.txt", "b.txt", "a.txt"]
file_paths.uniq.each do |path|
puts "Processing #{path}"
end
Building filter lists
categories = ["books", "games", "books", "music"]
menu_items = categories.uniq
Real Codebase Usage
In real Ruby projects, uniq is often used as part of a data-cleaning pipeline.
Common pattern: sanitize then deduplicate
emails = ["a@example.com", "b@example.com", "a@example.com"]
clean_emails = emails.map(&:downcase).uniq
This normalizes values first, then removes duplicates.
Common pattern: deduplicate before querying
ids = params[:user_ids].uniq
users = User.where(id: ids)
This avoids unnecessary repeated IDs.
Common pattern: guard clauses with empty arrays
def fetch_users(ids)
ids = ids.uniq
return [] if ids.empty?
User.where(id: ids)
end
Common pattern: combine arrays, then deduplicate
all_roles = default_roles + custom_roles
all_roles = all_roles.uniq
Destructive updates when mutation is intended
Common Mistakes
1. Confusing uniq with uniq!
uniq returns a new array.
uniq! changes the existing array.
numbers = [1, 1, 2]
numbers.uniq
puts numbers.inspect
# => [1, 1, 2]
Why? Because the result of uniq was not assigned.
Correct:
numbers = [1, 1, 2]
numbers = numbers.uniq
# or
numbers.uniq!
2. Expecting the result to be sorted
numbers = [3, 1, 3, 2, 1]
puts numbers.uniq.inspect
# => [3, 1, 2]
uniq removes duplicates, but it does not sort.
If you want both deduplication and sorting:
puts numbers.uniq.sort.inspect
# => [1, 2, 3]
Comparisons
| Approach | Changes original array? | Return value | Best use |
|---|---|---|---|
array.uniq | No | New array with duplicates removed | When you want to keep the original |
array.uniq! | Yes | Modified array, or nil if unchanged | When you intentionally want in-place modification |
Manual loop + include? | Usually no | Depends on implementation | Rarely needed for basic deduplication |
array.uniq.sort | No | New unique and sorted array | When you need uniqueness and order sorted |
uniq vs
Cheat Sheet
# Remove duplicates and return a new array
array.uniq
# Remove duplicates by modifying the original array
array.uniq!
Key rules
uniqdoes not modify the original array.uniq!does modify the original array.uniqpreserves the order of first appearance.uniqdoes not sort values.uniq!returnsnilif no changes were made.
Examples
[1, 2, 2, 1].uniq
# => [1, 2]
arr = [1, 1, 2]
arr.uniq!
# arr is now [1, 2]
Common combinations
array.uniq.sort # unique then sorted
array.map(&:downcase).uniq
array.compact.uniq # remove nil values, then duplicates
Watch out for
FAQ
How do I remove duplicates from an array in Ruby?
Use uniq:
array.uniq
It returns a new array with duplicates removed.
What is the difference between uniq and uniq! in Ruby?
uniq returns a new array. uniq! changes the original array in place.
Does Ruby uniq keep the original order?
Yes. Ruby keeps the first occurrence of each element and preserves that order.
Does uniq remove all repeated values from an array of strings?
Yes, as long as the strings are equal.
["a", "b", "a"].uniq
# => ["a", "b"]
Why does uniq! return nil sometimes?
If the array already has no duplicates, uniq! makes no change and returns nil.
Mini Project
Description
Build a small Ruby script that cleans a list of repeated email addresses before sending a newsletter. This demonstrates how deduplication prevents sending the same message multiple times.
Goal
Create a Ruby program that removes duplicate email addresses and prints the cleaned list.
Requirements
- Store a list of email addresses in an array with some duplicates.
- Remove duplicate email addresses using a built-in Ruby method.
- Keep the original order of the first occurrence.
- Print both the original array and the cleaned array.
Keep learning
Related questions
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Convert a Unix Timestamp to Ruby DateTime
Learn how to convert Unix timestamps to Ruby DateTime and Time objects, with examples, differences, pitfalls, and practical Ruby usage.