Array#rotate

Updated April 1, 2026 · Array Methods
ruby array rotate shift stdlib

Array#rotate returns a new array with all elements shifted cyclically to the left until the element at the given offset becomes the first element. It is useful for cycling through elements in a circular fashion — the last element wraps around to the back.

Basic Usage

fruits = ["apple", "banana", "cherry", "date"]

rotated = fruits.rotate
puts rotated   # => ["banana", "cherry", "date", "apple"]
puts fruits    # => ["apple", "banana", "cherry", "date"]

By default, rotate uses an offset of 1, shifting the first element to the end.

Using an Offset

Pass an integer to control which element becomes first:

days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

# Positive offset: count from the left
puts days.rotate(2)   # => ["Wednesday", "Thursday", "Friday", "Monday", "Tuesday"]

# Negative offset: count from the right
puts days.rotate(-1)   # => ["Friday", "Monday", "Tuesday", "Wednesday", "Thursday"]

# Offset of 0: no rotation
puts days.rotate(0)    # => ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

rotate vs shift

Both rotate and shift involve the first element, but they behave differently:

  • rotate moves the first element to the end, returning a new array — the original is unchanged
  • shift removes the first element entirely, reducing the array’s length
queue = ["first", "second", "third"]

rotated = queue.rotate
puts rotated   # => ["second", "third", "first"]
puts queue     # => ["first", "second", "third"]  — unchanged

shifted = queue.shift
puts shifted   # => "first"
puts queue     # => ["second", "third"]  — element removed

In-Place Rotation with rotate!

The bang variant rotate! rotates the array in place, modifying the original:

order = ["A", "B", "C", "D"]

order.rotate!
puts order   # => ["B", "C", "D", "A"]

rotate is ideal for cycling through items like a carousel — each call advances to the next item:

slides = ["intro", "features", "pricing", "contact"]

current = slides.rotate
puts "Showing: #{current.first}"   # => "Showing: features"

current = current.rotate
puts "Showing: #{current.first}"    # => "Showing: pricing"

current = current.rotate
puts "Showing: #{current.first}"    # => "Showing: contact"

current = current.rotate
puts "Showing: #{current.first}"    # => "Showing: intro"

Round-Robin Scheduling

Distribute tasks or games in a round-robin fashion:

teams = ["Red", "Blue", "Green", "Yellow"]

# Generate round 1 pairings
round1 = teams.rotate
pairings = round1.each_slice(2).to_a
puts pairings   # => [["Blue", "Green"], ["Yellow", "Red"]]

# Advance for round 2
round2 = round1.rotate
pairings = round2.each_slice(2).to_a
puts pairings   # => [["Green", "Yellow"], ["Red", "Blue"]]

Rotating Work Schedules

Assign rotating shifts fairly across team members:

staff = ["Alice", "Bob", "Carol", "Diana"]

def assign_shift(staff, week)
  rotated = staff.rotate(week - 1)
  rotated[0]
end

puts "Week 1: #{assign_shift(staff, 1)}"   # => "Week 1: Bob"
puts "Week 2: #{assign_shift(staff, 2)}"   # => "Week 2: Carol"
puts "Week 3: #{assign_shift(staff, 3)}"   # => "Week 3: Diana"
puts "Week 4: #{assign_shift(staff, 4)}"   # => "Week 4: Alice"

Return Value

  • rotate returns a new array with elements rotated; the original is unchanged
  • rotate! returns the same array (self) after rotating in place
letters = ["a", "b", "c"]

new_arr = letters.rotate
puts new_arr.class   # => Array
puts letters.class   # => Array (unchanged)

same_arr = letters.rotate!
puts same_arr.class  # => Array (same object)
puts same_arr.equal?(letters)   # => true

Performance Note

rotate has O(n) time complexity because it creates a new array and copies all elements. The space complexity is also O(n) due to the new array allocation.

rotate! has the same time complexity but avoids allocation since it modifies the array in place (O(n) time, O(1) extra space).

See Also