Array#reverse
.reverse returns a new array with elements in reverse order. .reverse! reverses the array in place.
Brief Intro
reverse creates a new array with elements in reverse order. reverse! modifies the original array. Both are useful when you need to process elements backward. You might want to display data in reverse order. You might also need to implement algorithms that work from the end toward the beginning.
The difference between the two methods matters when object identity is part of the design. If you want a new list and need to preserve the original, use reverse. If a caller expects the same object to change in place, use reverse! and make that choice clear in the method name.
Signature
| Method | Parameters | Return Type |
|---|---|---|
reverse | none | Array |
reverse! | none | Array (self) |
Code Examples
Basic Reverse
array = [1, 2, 3, 4, 5]
array.reverse
# => [5, 4, 3, 2, 1]
array
# original unchanged
In-Place Reverse with reverse!
The bang version reverse! changes the original collection in place rather than allocating a new one. This matters when memory is tight or when you want other references to the same object to see the updated order. The example below calls reverse! on a list and then inspects it afterward to confirm the mutation took effect.
array = [1, 2, 3, 4, 5]
array.reverse!
# => [5, 4, 3, 2, 1]
array
# original modified
Reversing strings in an array
Reversing an array of strings is the same operation as reversing any other list — reverse does not look inside the elements, it only rearranges their positions. The snippet below reverses three fruit names and shows that each string arrives at the opposite end of the sequence while the strings themselves stay intact.
words = ["apple", "banana", "cherry"]
words.reverse
# => ["cherry", "banana", "apple"]
Practical use: processing last items first
Processing items from last to first is a natural fit for reverse. Instead of writing a manual index loop that counts backward, you reverse the collection and iterate forward. This reads more clearly and avoids off-by-one mistakes that crop up with reverse-index arithmetic. The example below walks through a task pipeline in cleanup order.
tasks = ["design", "code", "test", "deploy"]
# Process tasks in reverse order
tasks.reverse.each do |task|
puts "Cleaning up: #{task}"
end
# Output:
# Cleaning up: deploy
# Cleaning up: test
# Cleaning up: code
# Cleaning up: design
Using with other array methods
Combining reverse with methods like last, sort, and map produces compact data transformation pipelines. Getting the last N elements in reverse order with last(3).reverse is cleaner than negative-index slicing, and sort.reverse gives you descending order without a custom block.
numbers = [1, 2, 3, 4, 5]
# Get last 3 elements, reversed
numbers.last(3).reverse
# => [5, 4, 3]
# Reverse after sorting
numbers.sort.reverse
# => [5, 4, 3, 2, 1]
# Reverse each element (for arrays of strings)
["dog", "cat", "bird"].map(&:reverse)
# => ["god", "tac", "drib"]
Building a stack-based processing pipeline
Reversing a sequence and iterating forward is a clean idiom for processing items from newest to oldest. Browser history, undo stacks, and event logs all fit this pattern. The code below walks through a page history in reverse, caching each page from most recent to least recent.
history = ["page1", "page2", "page3", "page4"]
# Navigate back through history
history.reverse.each do |page|
puts "Caching: #{page}"
end
# Output:
# Caching: page4
# Caching: page3
# Caching: page2
# Caching: page1
Reversing multi-dimensional arrays
reverse operates on the top-level elements only — it does not recurse into nested arrays. For a matrix, this means reversing the row order without touching the elements inside each row. To reverse both dimensions, chain reverse on the outer array with map(&:reverse) on each inner row.
matrix = [[1, 2], [3, 4], [5, 6]]
# Reverse the rows
matrix.reverse
# => [[5, 6], [3, 4], [1, 2]]
# Reverse each row
matrix.map(&:reverse)
# => [[2, 1], [4, 3], [6, 5]]
# Both: reverse rows then reverse each row
matrix.reverse.map(&:reverse)
# => [[6, 5], [4, 3], [2, 1]]
Return Value
reversereturns a new list with elements in reverse order. The original array remains unchanged.reverse!returns self (the modified array), allowing method chaining.
Edge Cases
- Empty array returns a new empty array.
Empty and single-element collections are the natural edge cases to check. An empty list reversed is still empty, and a single-element list reversed returns that element in a new wrapper — both behaviours follow naturally from the definition without any special-casing. The short snippets below confirm this for both the safe and bang variants.
[].reverse
# => []
[].reverse!
# => []
- Single-element array returns itself (new list for
reverse, same object forreverse!).
A single-element array reversed is still a single-element array — the element has nothing to swap with. The safe version reverse allocates a new one-element array, while reverse! returns the same object unchanged since there is no reordering to perform.
[42].reverse
# => [42]
[42].reverse!
# => [42]
reverse is a small, focused method that communicates intent clearly: you want to walk through a collection from the opposite end. Use the safe version when the original order must be preserved, and reach for reverse! when the array is a working buffer that should be modified in place.